misc/060tsys/t30main.s
	.include	t00iocs.equ
	.include	t01dos.equ
	.include	t02const.equ
	.include	t08debug.equ
	.include	t09version.equ

;__DEBUG__	equ	1

;__USE_DISPLACMENT__	equ	1

	.cpu	68060

  .ifdef __USE_DISPLACEMENT__
r	reg	-deviceHeader.w(a4)	;t10head.sにあるラベル以外には使わないこと
  .else
r	reg	-0
  .endif

;----------------------------------------------------------------
;常駐部分の末尾
keepTail::

;----------------------------------------------------------------
;デバイス初期化
deviceInitialize::
	movem.l	d1-d7/a0-a4/a6,-(sp)
  .ifdef __USE_DISPLACEMENT__
	lea.l	deviceHeader,a4
  .endif
  debug 'device initialize start',0

	lea.l	(banner,pc),a1
	bsr	print

;----------------------------------------------------------------
;MPU,Humanのチェック
	bsr	mpuCheck
	bmi	deviceInitializeError
	bsr	humanCheck
	bmi	deviceInitializeError
  debug 'MPU,ROM,Human check ok',0

;----------------------------------------------------------------
;データキャッシュがOFFのときキャッシュをプッシュせずに無効化する
	cmpi.b	#4,$0CBC.w
	blo	99f
	movec.l	cacr,d0
	btst.l	#CACR_EDC_BIT,d0
	bne	@f
	cinva	dc
@@:	cinva	ic
99:

;----------------------------------------------------------------
;store/load bypass機能を無効にする
	cmpi.b	#6,$0CBC.w
	bne	10f
	movec.l	pcr,d0
	bset.l	#5,d0			;disable store/load bypass
	movec.l	d0,pcr
10:

;----------------------------------------------------------------
;ローカルメモリの容量チェック
	bsr	getLocalMemorySize
	move.l	d0,(localMemorySize)r
	move.l	d1,(localMemoryStart)r
	add.l	d0,d1
	move.l	d1,(localMemoryEnd)r
  debug 'local memory size checked',0

;----------------------------------------------------------------
;管理領域の範囲の初期化
	move.l	#keepTail,d0
	add.l	#$00001FFF,d0		;mainLowerStartはページサイズに合わせる
	and.l	#$FFFFE000,d0
	move.l	d0,(mainLowerStart)r
	move.l	d0,(mainLowerEnd)r
	move.l	$1C00.w,d0
	and.l	#$FFFFE000,d0
	move.l	d0,(mainUpperStart)r
	move.l	d0,(mainUpperEnd)r
	tst.l	(localMemorySize)r
	beq	@f
	move.l	(localMemoryStart)r,d0
	move.l	d0,(localLowerStart)r
	move.l	d0,(localLowerEnd)r
	move.l	(localMemoryEnd)r,d0
	move.l	d0,(localUpperStart)r
	move.l	d0,(localUpperEnd)r
@@:
  debug 'management area set',0

;----------------------------------------------------------------
;転送バッファの領域の初期化
	clr.l	(tempBufferSize)r
  debug 'temporary buffer vanished',0

;----------------------------------------------------------------
;メインメモリ上のRAMDISKの領域の初期化
	move.l	(mainUpperStart)r,d0
	move.l	d0,(mainRamdiskAreaStart)r
	move.l	d0,(mainRamdiskAreaEnd)r
	clr.l	(mainRamdiskAreaSize)r
  debug 'main RAMDISK vanished',0

;ローカルメモリ上のRAMDISKの領域の初期化
	move.l	(localLowerStart)r,d0
	move.l	d0,(localRamdiskAreaStart)r
	move.l	d0,(localRamdiskAreaEnd)r
	clr.l	(localRamdiskAreaSize)r
  debug 'local RAMDISK vanished',0

;----------------------------------------------------------------
;メインメモリのサイズの初期化
	move.l	#-1,(mainMemorySize)r
  debug 'main memory size initialized',0

;----------------------------------------------------------------
;パラメータの解釈
;	mainLowerを使うもの
;		tempBuffer
;		dosBusErr
;	mainUpperを使うもの
;		mainRamdiskArea
;		descArea
;	localLowerを使うもの
;		localRamdiskArea
;	localLowerとlocalUpperの間がhimemArea
;	localUpperを使うもの
;		localRom
;		descArea
  debug 'parameter check start',0
;68030のとき-ntを強制的に指定する
	cmpi.b	#3,$0CBC.w
	bhi	@f
	st.b	(noTranslation)r
@@:
	movea.l	(18,a5),a6		;パラメータのアドレス
1:	tst.b	(a6)+
	bne	1b
	tst.b	(a6)
	beq	2f
	movea.l	a6,a0
	bsr	getParam
	bra	1b
2:
  debug 'parameter check end',0

;----------------------------------------------------------------
;デスクリプタの領域のサイズを決定する
;	-tsの指定があればそのまま
;	-tsの指定がおかしければ0になっているのでここで設定される
	tst.b	(noTranslation)r
	bne	99f
	bsr	defaultDescAreaSize
  debug 'desc area size set',0
99:

;----------------------------------------------------------------
;メインメモリ上のRAMDISKの領域をページサイズの倍数まで切り下げる
	move.l	(mainRamdiskAreaStart)r,d0
	and.l	(pageMask)r,d0
	move.l	d0,(mainRamdiskAreaStart)r
	move.l	d0,(mainUpperStart)r
  debug 'main RAMDISK area resized',0

;----------------------------------------------------------------
;転送バッファの確保
	tst.l	(tempBufferSize)r
	bne	@f
	move.l	#DEFAULT_BUFFER_SIZE,d0	;転送バッファはページサイズの倍数にすること
	move.l	d0,(tempBufferSize)r
	move.l	(mainLowerEnd)r,d1
	add.l	#$00001FFF,d1		;転送バッファはページ位置に合わせる
	and.l	#$FFFFE000,d1
	move.l	d1,(tempBufferStart)r
	add.l	d0,d1
	move.l	d1,(tempBufferEnd)r
	move.l	d1,(mainLowerEnd)r
	move.l	(mainUpperStart)r,d0
	sub.l	d1,d0
	cmp.l	#128*1024,d0
	blt	tempBufferOver
@@:

;----------------------------------------------------------------
;ADPCM転送バッファの確保と初期化
	tst.b	(patchIocsAdpcm)r
	beq	@f
	move.l	(adpcmBufferSize)r,d0	;設定済み
	move.l	(mainLowerEnd)r,d1
	add.l	#$00001FFF,d1		;転送バッファはページ位置に合わせる
	and.l	#$FFFFE000,d1
	move.l	d1,(adpcmBufferStart)r
	move.l	d1,(adpcmBufferPtr0)r
	add.l	d0,d1
	move.l	d1,(adpcmBufferPtr1)r
	add.l	d0,d1
	move.l	d1,(adpcmBufferEnd)r
	add.l	#$00001FFF,d1		;転送バッファはページ位置に合わせる
	and.l	#$FFFFE000,d1
	move.l	d1,(mainLowerEnd)r
	bsr	dmac3Initialize
;1ページだけなのでメモリ不足チェックは省略
@@:

;----------------------------------------------------------------
;_BUS_ERR用の仮のベクタテーブルと仮のスーパーバイザスタックの領域を確保する
	move.l	(mainLowerEnd)r,d0
	move.l	d0,(dosBusErrVbr)r
	add.l	#1024+1024,d0		;2KBなのでメモリ不足チェックは省略
	move.l	d0,(dosBusErrSsp)r
	move.l	d0,(mainLowerEnd)r

;----------------------------------------------------------------
;ローカルメモリ上のRAMDISKの領域をページサイズの倍数まで切り上げる
	move.l	(localRamdiskAreaEnd)r,d0
	add.l	(pageOffsetMask)r,d0
*****pageMaskでマスクすると論理アドレス空間の末尾が0になってしまう
*****	and.l	(pageMask)r,d0
	and.w	(pageMask+2)r,d0
	move.l	d0,(localRamdiskAreaEnd)r
	move.l	d0,(localLowerEnd)r
  debug 'local RAMDISK area resized',0

;----------------------------------------------------------------
;ローカルメモリ上にROMをコピーする
	tst.b	(noTranslation)r
	bne	99f
	tst.b	(localRomArea)r
	beq	2f
	movea.l	#$00F00000,a1
	movea.l	(localRomStart)r,a0
1:	move16	(a1)+,(a0)+
	cmpa.l	#$01000000,a1
	blo	1b
	movea.l	(localRomStart)r,a0
	add.l	#$00FF0000-$00F00000,a0
	move.l	#'loca',(a0)+
	move.l	#'lRom',(a0)+

;ROMVER=$15970213のバグを修正
	IOCS	_ROMVER
	cmp.l	#$15970213,d0
	bne	9f
	movea.l	(localRomStart)r,a0
	add.l	#$00FFB32C-$00F00000,a0
	cmpi.l	#$4A75002A,(a0)
	bne	@f
	move.l	#$4A75042A,(a0)
@@:
	move.b	#$08,DCR2
	move.b	#$05,MFC2
	move.b	#$03,CPR2
	move.b	#$05,DFC2
;	move.b	#$05,BFC2
;	move.b	#$68,NIV2
;	move.b	#$69,EIV2
9:

;ROMVER=$15970529のバグを修正
	IOCS	_ROMVER
	cmp.l	#$15970529,d0
	bne	9f
;ソフトキーボードが表示されている状態でキーを押すとハングアップするバグを修正
	movea.l	(localRomStart)r,a0
	add.l	#$00FF5004-$00F00000,a0
	cmpi.w	#$2057,(a0)		;movea.l (sp),a0
	bne	@f
	move.w	#$205F,(a0)		;movea.l (sp)+,a0
@@:
9:

;SCSIのDMA転送をPACKしてみる(700KB→500KBと、かえって遅くなるらしい)
;	IOCS	_ROMVER
;	cmp.l	#$14970107,d0
;	bne	@f
;	movea.l	(localRomStart)r,a0
;	add.l	#$00FFDE60-$00F00000,a0
;	cmpi.w	#$80B1,(a0)
;	bne	@f
;	move.w	#$8081,(a0)
;@@:
	bsr	cache_flush
2:
  debug 'local ROM area set',0
99:

;----------------------------------------------------------------
;デスクリプタの領域の確保
	tst.b	(noTranslation)r
	bne	99f
	tst.b	(localAreaDescriptor)r
	beq	1f
	move.l	(localUpperStart)r,d0
	sub.l	(descAreaSize)r,d0
	and.l	(pageMask)r,d0
	cmp.l	(localLowerEnd)r,d0
	bcc	2f
	sf.b	(localAreaDescriptor)r
;メインに作る
1:	move.l	(mainUpperStart)r,d0
	sub.l	(descAreaSize)r,d0
	and.l	(pageMask)r,d0
	move.l	(mainLowerEnd)r,d1
	add.l	#128*1024,d1
	cmp.l	d1,d0
	blt	descAreaOver
	move.l	d0,(mainUpperStart)r
	bra	3f
;ローカルに作る
2:	move.l	d0,(localUpperStart)r
3:	move.l	d0,(descAreaStart)r
	add.l	(descAreaSize)r,d0
	move.l	d0,(descAreaEnd)r
  debug 'descriptor area allocated',0
99:

;----------------------------------------------------------------
;_HIMEMの領域を設定
	clr.l	(himemAreaStart)r
	clr.l	(himemAreaEnd)r
	clr.l	(himemAreaSize)r
	tst.l	(localMemorySize)r
	beq	2f
	move.l	(localLowerEnd)r,d1
	move.l	(localUpperStart)r,d2
	move.l	d2,d0
	sub.l	d1,d0
	bls	2f			;HIMEMに空きエリアがない
	move.l	d0,(himemAreaSize)r
	move.l	d1,(himemAreaStart)r
	move.l	d2,(himemAreaEnd)r
	movea.l	d1,a0
	lea.l	(User,a0),a1
;;;	cmpi.l	#'060t',(a1)
;;;	beq	2f			;初期化されている
	move.l	#'060t',(a1)+
	move.l	#'urbo',(a1)+
	move.l	#'HIME',(a1)+
	move.l	#'M'<<24,(a1)+
	clr.l	(Prev,a0)
	move.l	$1C20.w,(Proc,a0)	;Humanのメモリ管理ポインタ
	move.l	a1,(Tail,a0)
	clr.l	(Next,a0)
2:
  debug 'HIMEM area initialized',0

;----------------------------------------------------------------
;スレッド間の排他制御情報を初期化する
	tst.b	(backgroundFlag)r
	beq	9f
;メインスレッドの排他制御情報を初期化する
	lea.l	(mainExclusive)r,a2
;標準ハンドラを作成する
	moveq.l	#0,d2
1:	move.w	d2,-(sp)
	DOS	_DUP			;標準ハンドラを複製する
	addq.l	#2,sp			;エラーが発生してはならない
	move.w	d0,(xStdin,a2,d2.w*2)
	addq.w	#1,d2
	cmp.w	#5,d2
	blo	1b
;ドライブ管理テーブルのアドレスを設定する
	move.l	$1C38.w,(xDriveTablePtr,a2)	;現在のドライブ管理テーブル
9:

;----------------------------------------------------------------
;乱数系列を初期化する
	DOS	_GETDATE
	move.l	d0,d1
	DOS	_GETTIME
	add.w	d1,d0
	swap.w	d1
	add.w	d1,d0
	move.l	d0,d1
	bsr	srand
	move.l	d1,d0
	bsr	randomize

;----------------------------------------------------------------
;
;	以降は中断不可
;
;----------------------------------------------------------------

;----------------------------------------------------------------
;Humanにパッチをあてる
	tst.b	(unitCounter)r		;RAMDISKがなければ,
	bne	@f			;RAMDISKのチェックは無意味なので省略する
	move.l	#callDeviceNoRamdisk,patchHumanCallDevice+2
@@:
	bsr	patchHuman
	bmi	deviceInitializeError
  debug 'Human68k patched',0

;----------------------------------------------------------------
;メインメモリを切り詰める
	move.l	(mainUpperStart)r,$1C00.w
  debug 'main memory resized',0

;----------------------------------------------------------------
;アドレス変換テーブルを作る
	tst.b	(noTranslation)r
	bne	99f
	bsr	makeTranslationTable
  debug 'address translation table created',0
99:

;----------------------------------------------------------------
;ベクタ設定
	move.b	(localRomArea)r,d0
	or.b	(localSystemArea)r,d0
	beq	@f
	lea.l	(vectorInfoHumanTrap10)r,a0
	bsr	setVector
  debug 'TRAP#10 vector set',0
@@:

	lea.l	(vectorInfoPRIVILEGE)r,a0
	bsr	setVector
	lea.l	(vectorInfoFLINE)r,a0
	bsr	setVector
	lea.l	(vectorInfoBSUN)r,a0
	bsr	setVector
	lea.l	(vectorInfoINEX)r,a0
	bsr	setVector
	lea.l	(vectorInfoDZ)r,a0
	bsr	setVector
	lea.l	(vectorInfoUNFL)r,a0
	bsr	setVector
	lea.l	(vectorInfoOPERR)r,a0
	bsr	setVector
	lea.l	(vectorInfoOVFL)r,a0
	bsr	setVector
	lea.l	(vectorInfoSNAN)r,a0
	bsr	setVector
	lea.l	(vectorInfoUNSUPP)r,a0
	bsr	setVector
	lea.l	(vectorInfoEFFADD)r,a0
	bsr	setVector
	lea.l	(vectorInfoUNINT)r,a0
	bsr	setVector
  debug '060SP vector set',0

	lea.l	(spBanner,pc),a1
	bsr	print

	tst.b	(patchIocsAdpcm)r
	beq	@f
	lea.l	(vectorInfoIocsAdpcmout)r,a0
	bsr	setVector
	lea.l	(vectorInfoIocsAdpcminp)r,a0
	bsr	setVector
	lea.l	(vectorInfoIocsAdpcmaot)r,a0
	bsr	setVector
	lea.l	(vectorInfoIocsAdpcmain)r,a0
	bsr	setVector
	lea.l	(vectorInfoIocsAdpcmlot)r,a0
	bsr	setVector
	lea.l	(vectorInfoIocsAdpcmlin)r,a0
	bsr	setVector
	lea.l	(vectorInfoIocsAdpcmsns)r,a0
	bsr	setVector
	lea.l	(vectorInfoIocsAdpcmmod)r,a0
	bsr	setVector
  debug 'IOCS ADPCM vector set',0
@@:

	tst.b	(softwareIocsDma)r
	beq	@f
	lea.l	(vectorInfoIocsDmamove)r,a0
	bsr	setVector
	lea.l	(vectorInfoIocsDmamovA)r,a0
	bsr	setVector
	lea.l	(vectorInfoIocsDmamovL)r,a0
	bsr	setVector
	lea.l	(vectorInfoIocsDmamode)r,a0
	bsr	setVector
  debug 'IOCS DMA vector set',0
@@:

	lea.l	(vectorInfoIocsSysStat)r,a0
	bsr	setVector
  debug 'SYS_STAT vector set',0

	cmpi.w	#_SCSIDRV*$0100+$00FF,$0400+_SCSIDRV*4.w
	beq	@f			;_SCSIDRVは登録されていない
	cmpi.w	#$00FF,$0400+_SCSIDRV*4.w
	beq	@f			;_SCSIDRVは登録されていない
	SCSI	_S_REVISION
	move.w	d0,(scsiRevisionCode)r
	lea.l	(vectorInfoIocsScsidrv)r,a0
	bsr	setVector
  debug 'SCSIDRV vector set',0
@@:

	lea.l	(vectorInfoIocsPrnintst)r,a0
	bsr	setVector
	lea.l	(vectorInfoPrnint)r,a0
	bsr	setVector
  debug 'PRNINTST vector set',0

	tst.b	(useIocsHimem)r
	beq	@f
	lea.l	(vectorInfoIocsHimem)r,a0
	bsr	setVector
  debug 'HIMEM vector set',0
@@:

	lea.l	(vectorInfoDosExec)r,a0
	bsr	setVector
  debug 'EXEC vector set',0

;	tst.b	(useJointMode)r
;	beq	@f
	lea.l	(vectorInfoDosMalloc)r,a0
	bsr	setVector
	lea.l	(vectorInfoDos0Malloc2)r,a0
	bsr	setVector
	lea.l	(vectorInfoDosMalloc2)r,a0
	bsr	setVector
	lea.l	(vectorInfoDos0Malloc3)r,a0
	bsr	setVector
	lea.l	(vectorInfoDosMalloc3)r,a0
	bsr	setVector
	lea.l	(vectorInfoDos0Malloc4)r,a0
	bsr	setVector
	lea.l	(vectorInfoDosMalloc4)r,a0
	bsr	setVector
	lea.l	(vectorInfoDosMfree)r,a0
	bsr	setVector
	lea.l	(vectorInfoDosSetblock)r,a0
	bsr	setVector
	lea.l	(vectorInfoDos0Setblock2)r,a0
	bsr	setVector
	lea.l	(vectorInfoDosSetblock2)r,a0
	bsr	setVector
	lea.l	(vectorInfoDos0SMalloc)r,a0
	bsr	setVector
	lea.l	(vectorInfoDosSMalloc)r,a0
	bsr	setVector
	lea.l	(vectorInfoDos0SMalloc2)r,a0
	bsr	setVector
	lea.l	(vectorInfoDosSMalloc2)r,a0
	bsr	setVector
	lea.l	(vectorInfoDos0SMfree)r,a0
	bsr	setVector
	lea.l	(vectorInfoDosSMfree)r,a0
	bsr	setVector
	lea.l	(vectorInfoDos0SProcess)r,a0
	bsr	setVector
	lea.l	(vectorInfoDosSProcess)r,a0
	bsr	setVector
  debug 'memory doscall vector set',0
@@:

	tst.b	(backgroundFlag)r
	beq	@f
	lea.l	(vectorInfoDosOpenPr)r,a0
	bsr	setVector
	lea.l	(vectorInfoDosKillPr)r,a0
	bsr	setVector
	lea.l	(vectorInfoDosChangePr)r,a0
	bsr	setVector
  debug 'background doscall vector set',0
@@:

;----------------------------------------------------------------
;アドレス変換開始
	tst.b	(noTranslation)r
	bne	99f
	bsr	enableTranslation
  debug 'address translation enabled',0
99:

;----------------------------------------------------------------
;キャッシュなどの状態を初期化
;EBC=1,ESB=1,ESS=1,EDC=0,EIC=0
;	データキャッシュと命令キャッシュの状態は,
;	060turbo.sysの初期化が終わってHumanに戻った直後に,
;	パッチによってSRAMの設定になる
	move.w	#$C007,d1
	moveq.l	#%11100,d2
	IOCS	_SYS_STAT
  debug 'branch cache, store buffer, superscaler enabled',0

;----------------------------------------------------------------
;ベクタ領域からHuman本体の末尾までと060turbo.sysの常駐部分をローカルメモリに移動する
	tst.b	(localSystemArea)r
	beq	9f
	PUSH_MMU_SFC_DFC	d0
	move.l	(localSystemStart)r,d3	;コピー先
	suba.l	a1,a1			;コピー元
1:	cmpa.l	#$0001447A.and.PAGE_MASK,a1	;Human本体の末尾
	bne	@f
	move.l	#deviceHeader,d0	;060turbo.sysの先頭
	add.l	#PAGE_OFFSET_SIZE-1,d0
	and.l	#PAGE_MASK,d0
	movea.l	d0,a1
@@:
;
	bsr	getDesc
	move.l	d0,d2			;現在のページデスクリプタ
	and.l	(pageOffsetMask)r,d2	;属性だけ取り出す
	or.l	d3,d2			;コピー先のアドレスを使う
	movea.l	d3,a2			;コピー先
	movea.l	a1,a3			;コピー元
	move.l	(pageOffsetSize)r,d0
	lsr.l	#4,d0
;割り込みを止めた状態で大急ぎでコピーしてすぐに切り替える
;コピー元のアドレスでコピー先が見えるようにする
	PUSH_SR_DI
2:	move16	(a3)+,(a2)+
	subq.l	#1,d0
	bne	2b
	movea.l	d3,a2
	cpushp	bc,(a2)
	moves.l	d2,(a0)
	pflusha
	POP_SR
;念のためコピー先のアドレスでコピー元が見えるようにしておく
	exg.l	d3,a1
	bsr	getDesc			;コピー先
	and.l	(pageOffsetMask)r,d2	;属性だけ取り出す
	or.l	d3,d2			;コピー元のアドレスを使う
	moves.l	d2,(a0)
	pflusha
	exg.l	d3,a1
;
	add.l	(pageOffsetSize)r,d3
	adda.l	(pageOffsetSize)r,a1
	cmp.l	(localSystemEnd)r,d3
	blo	1b
	POP_SFC_DFC	d0
  debug 'local system started',0
9:

;----------------------------------------------------------------
;デバイス初期化終了
	tst.b	(unitCounter)r
	bne	1f
;ユニット数が0のときキャラクタデバイスのふりをする
	move.w	#$8000,(deviceHeader+dhType)r
	move.l	#'/*06',(deviceHeader+dhName)r
	move.l	#'0T*/',(deviceHeader+dhName+4)r
	bra	2f
1:	move.b	(unitCounter)r,(13,a5)	;ユニット数
	move.l	#bpbTablePointer,(18,a5)	;BPBテーブルのポインタのテーブル
2:	move.l	(mainLowerEnd)r,(14,a5)	;デバイスドライバの末尾+1
	moveq.l	#0,d0
  debug 'device initialize end',0

deviceInitializeExit:
	movem.l	(sp)+,d1-d7/a0-a4/a6
	rts

banner:
	.dc.b	13,10
*	.dc.b	$1B,'[1m'
	.dc.b	'060turbo.sys version ',VERSION
*	.dc.b	$1B,'[1m'
	.dc.b	' ',DATE
	.dc.b	' by M.Kamada',13,10,0

spBanner:
	.dc.b	'M68060 Software Package Copyright (C) Motorola Inc.',13,10
	.dc.b	0
	.even

deviceInitializeError:
	move.w	#$700D,d0
	bra	deviceInitializeExit

tempBufferOver:
	lea.l	(@f,pc),a1
	bsr	print
	bra	deviceInitializeError
@@:	.dc.b	'転送バッファが確保できません',13,10,0
	.even

descAreaOver:
	lea.l	(@f,pc),a1
	bsr	print
	bra	deviceInitializeError
@@:	.dc.b	'デスクリプタの領域が確保できません',13,10,0
	.even

;----------------------------------------------------------------
;MPUを確かめる
;68060のときHumanが[$0CBC].b=$03にしてしまっている
;>d0.l:0=成功,-1=失敗
;>ccr:pl成功,mi=失敗
mpuCheck:
	movem.l	d1/a0-a2,-(sp)
	PUSH_SR_DI
	movea.l	sp,a1
	move.l	$0010,a2
	move.l	#110f,$0010.w		;Illegal Instruction
;MOVEC from SFCがなければ68000
	moveq.l	#0,d0
	lea.l	(80f,pc),a0
	movec.l	sfc,d0
;スケールファクタがなければ68010
	moveq.l	#1,d0
10:	moveq.l	#1,d1
	and.b	(10b-1,pc,d1.l*2),d1
	beq	80f
;CALLMがあれば68020
	.cpu	68020
	lea.l	(40f,pc),a0
	callm	#0,(20f,pc)
	moveq.l	#2,d0
	bra	80f

;モジュールデスクリプタ
20:	.dc.l	%0<<13|0<<24|0<<16	;option=0,type=0,accesslevel=0
	.dc.l	30f			;モジュールエントリポインタ
	.dc.l	0			;モジュールデータ領域ポインタ
	.dc.l	0
;モジュールエントリ
30:	.dc.w	15<<12			;Rn=sp
	rtm	sp
	.cpu	68060

;MOVEC from CAARがあれば68030
	.cpu	68030
40:	lea.l	(50f,pc),a0
	movec.l	caar,d0
	moveq.l	#3,d0
	bra	80f
	.cpu	68060

;MOVEC from MMUSRがあれば68040
	.cpu	68040
50:	lea.l	(60f,pc),a0
	movec.l	mmusr,d0
	moveq.l	#4,d0
	bra	80f
	.cpu	68060

;MOVEC from PCRがあれば68060
60:	lea.l	(70f,pc),a0
	movec.l	pcr,d0
	moveq.l	#6,d0
	bra	80f

;不明
70:	moveq.l	#0,d0
80:	move.b	d0,$0CBC.w
	move.l	a2,$0010.w
	POP_SR
	moveq.l	#0,d0
	cmpi.b	#3,$0CBC.w
	bhs	90f
	lea.l	(100f,pc),a1
	bsr	print
	moveq.l	#-1,d0
90:	movem.l	(sp)+,d1/a0-a2
	tst.l	d0
	rts

100:	.dc.b	'68030 以上ではありません',13,10,0
	.even

110:	movea.l	a1,sp
	jmp	(a0)

;----------------------------------------------------------------
;Human68kのバージョンを確かめる
humanCheck:
	DOS	_VERNUM
	cmp.w	#$0302,d0
	bne	9f
	moveq.l	#0,d0
	rts

9:	lea.l	(@f,pc),a1
	bsr	print
	moveq.l	#-1,d0
	rts
@@:	.dc.b	'Human のバージョンが違います',13,10,0
	.even

;----------------------------------------------------------------
;Humanにパッチをあてる
patchHuman::
	bsr	patchHuman302
	bmi	9f
	rts

9:	lea.l	(@f,pc),a1
	bsr	print
	moveq.l	#-1,d0
	rts
@@:	.dc.b	'Human が異常です',13,10,0
	.even

;----------------------------------------------------------------
;ベクタを設定する
;<a0.l:ベクタ情報
;	0000	.l	ベクタアドレス
;	0004	.l	元のベクタ
;	0008	.l	新しいベクタ
setVector::
	movem.l	a0-a1,-(sp)
	movea.l	(a0)+,a1		;ベクタアドレス
	move.l	(a1),(a0)+		;元のベクタを保存
	move.l	(a0),(a1)		;新しいベクタを設定
	movem.l	(sp)+,a0-a1
	rts

;----------------------------------------------------------------
;ローカルメモリの容量と先頭アドレスを返す
;	前提
;	・ローカルメモリの容量と先頭アドレスは$01000000(16MB)の倍数である
;	・ローカルメモリのアクセスでアクセスエラーや不具合によるデータの破損は発生しない
;	・このプログラムはスーパーバイザモードで実行される
;	・このプログラムとスーパーバイザスタックエリアは論理アドレス=物理アドレスの領域にある
;	・このプログラムとスーパーバイザスタックエリアのアドレスの上位8ビットは$00である
;	手順
;	・$00000000-$3FFFFFFF(1024MB)を$01000000(16MB)ずつ64個に区切る
;	・上位のブロックから順に同じオフセットに異なるデータを書き込む
;	・上位のブロックから順に書き込んだデータを読み出せれば存在すると判断する
;パラメータなし
;>d0.l:ローカルメモリの容量
;>d1.l:ローカルメモリの先頭アドレス
getLocalMemorySize::
	movem.l	d2-d5/a0,-(sp)
	moveq.l	#0,d0
;キャッシュ禁止
	movec.l	cacr,d4
	movec.l	d0,cacr
	CACHE_FLUSH	d3
;MMU禁止
	cmpi.b	#4,$0CBC.w
	blo	@f
	movec.l	tc,d3
	movec.l	d0,tc
	pflusha
;トランスペアレント変換禁止
	movec.l	dtt1,d2
	movec.l	d0,dtt1
	movec.l	dtt0,d5
	movec.l	d0,dtt0
@@:
;コントロールレジスタ保存
	movem.l	d2-d5,-(sp)
;ワークエリア確保
	lea.l	-4-64(sp),sp
;保存
	moveq.l	#$3F,d1			;ブロックの番号。$3F→$00
10:	move.l	d1,d0
	ror.l	#8,d0
	lea.l	(sp,d0.l),a0		;テストするアドレス
	move.b	(a0),4(sp,d1.l)		;保存
	dbra	d1,10b
;変更
	moveq.l	#$3F,d1			;ブロックの番号。$3F→$00
20:	move.l	d1,d0
	ror.l	#8,d0
	lea.l	(sp,d0.l),a0		;テストするアドレス
	move.b	d1,(a0)			;変更
	dbra	d1,20b
;比較と復元
	moveq.l	#$3F,d1			;ブロックの番号。$3F→$00
30:	move.l	d1,d0
	ror.l	#8,d0
	lea.l	(sp,d0.l),a0		;テストするアドレス
	cmp.b	(a0),d1			;比較
	seq.b	d0			;0=ない,-1=ある
	bne	40f
	move.b	4(sp,d1.l),(a0)		;(あるとき)復元
40:	move.b	d0,4(sp,d1.l)		;結果。0=ない,-1=ある
	dbra	d1,30b
	sf.b	4(sp)			;ブロック0はローカルメモリではない
;末尾
	moveq.l	#$3F,d1			;ブロックの番号。$3F→$00
50:	tst.b	4(sp,d1.l)
	dbne	d1,50b
	beq	70f			;ない
;ある
	move.l	d1,d0			;末尾のブロックの番号
;先頭
60:	tst.b	4(sp,d1.l)
	dbeq	d1,60b			;必ずeqで止まる
	addq.b	#1,d1
	ror.l	#8,d1			;先頭のブロックの先頭アドレス
	addq.b	#1,d0
	ror.l	#8,d0			;末尾のブロックの末尾アドレス+1
	sub.l	d1,d0			;長さ
	bra	80f
;ない
70:	moveq.l	#0,d0
	moveq.l	#0,d1
80:
;<d0.l:ローカルメモリの容量
;<d1.l:ローカルメモリの先頭アドレス
;ワークエリア開放
	lea.l	4+64(sp),sp
;コントロールレジスタ復元
	movem.l	(sp)+,d2-d5
;トランスペアレント変換復元
	cmpi.b	#4,$0CBC.w
	blo	@f
	movec.l	d5,dtt0
	movec.l	d2,dtt1
;MMU復元
	movec.l	d3,tc
@@:
;キャッシュ復元
	movec.l	d4,cacr
	movem.l	(sp)+,d2-d5/a0
	rts


;----------------------------------------------------------------
;ローカルメモリのサイズからデスクリプタの領域のサイズを決定する
defaultDescAreaSize::
	movem.l	d0-d1,-(sp)
	tst.l	(descAreaSize)r
	bne	2f			;既に指定されている
	move.l	#DEFAULT_DESC_SIZE_0,d1
	move.l	(localMemorySize)r,d0
	beq	1f			;本体16MBのみ
	move.l	#DEFAULT_DESC_SIZE_16,d1
	cmp.l	#16<<20,d0
	bls	1f			;本体16MB+ローカル16MB
	move.l	#DEFAULT_DESC_SIZE_32,d1
	cmp.l	#32<<20,d0
	bls	1f			;本体16MB+ローカル32MB
	move.l	#DEFAULT_DESC_SIZE_64,d1
	cmp.l	#64<<20,d0
	bls	1f			;本体16MB+ローカル64MB
	move.l	#DEFAULT_DESC_SIZE_128,d1
	cmp.l	#128<<20,d0
	bls	1f			;本体16MB+ローカル128MB
	move.l	#DEFAULT_DESC_SIZE_256,d1
	cmp.l	#256<<20,d0
	bls	1f			;本体16MB+ローカル256MB
	move.l	#DEFAULT_DESC_SIZE_384,d1
	cmp.l	#384<<20,d0
	bls	1f			;本体16MB+ローカル384MB
	move.l	#DEFAULT_DESC_SIZE_512,d1
	cmp.l	#512<<20,d0
	bls	1f			;本体16MB+ローカル512MB
	move.l	#DEFAULT_DESC_SIZE_768,d1
					;本体16MB+ローカル768MB
1:	move.l	d1,(descAreaSize)r
2:	movem.l	(sp)+,d0-d1
	rts

;----------------------------------------------------------------
;アドレス変換テーブルを作る
makeTranslationTable::
	movea.l	(descAreaStart)r,a0
	movea.l	(descAreaEnd)r,a1
;デスクリプタの領域に関連するワークを設定する
	move.l	a0,(descHead)r
;	move.l	a0,(rootDescHead)r
	lea.l	(ROOT_DESC_SIZE,a0),a2
	move.l	a2,(rootDescTail)r
;	move.l	a2,(pointerDescHead)r
	move.l	a2,(pointerDescTail)r
	move.l	(descAreaSize)r,d0
	move.l	(pageIndexWidth)r,d1
	lsr.l	d1,d0			;参照数カウンタの領域のサイズ
	move.l	a1,d1
	sub.l	d0,d1
	and.l	(pageDescMask)r,d1
	move.l	d1,(pageDescHead)r
	move.l	d1,(pageDescTail)r
;	move.l	d1,(pointerCounterHead)r
	move.l	a1,(pageCounterTail)r
;	move.l	a1,(descTail)r

;デスクリプタの領域を初期化する
	movea.l	(rootDescHead)r,a0
	movea.l	(pageDescTail)r,a1
@@:	clr.l	(a0)+
	cmpa.l	a1,a0
	blo	@b
	movea.l	(pageCounterTail)r,a1
@@:	move.l	#-1,(a0)+
	cmpa.l	a1,a0
	blo	@b

	MMU_SFC_DFC	d0

;メインメモリのアドレス変換
	lea.l	(physicalModeTable,pc),a2
	suba.l	a1,a1
1:	move.l	(a2)+,d2		;モード
	move.l	(a2)+,d0		;次のアドレス
6:	cmpa.l	d0,a1
	blo	7f
	move.l	(a2)+,d2		;モード
	move.l	(a2)+,d0		;次のアドレス
	bpl	6b
7:	subq.l	#8,a2
	add.l	a1,d2
	bsr	setDesc
	bmi	9f			;エラー無視
	adda.l	(pageOffsetSize)r,a1
	cmpa.l	#$01000000,a1
	bne	1b

	moveq.l	#$00000000,d1
2:	move.l	d1,d0
	bsr	copyPointerDesc
	add.l	#$00040000,d1
	adda.l	#$00040000,a1
	cmpa.l	#$02000000,a1
	bne	2b

3:	moveq.l	#$00000000,d0
	bsr	copyRootDesc
	adda.l	#$02000000,a1
	cmpa.l	#LOGICAL_SIZE,a1
	bne	3b

;ローカルメモリのアドレス変換
	move.l	(localMemorySize)r,d1
	beq	5f
	clr.w	d3
	move.b	localMemoryCacheMode,d3
	lsl.w	#PD_CM_BIT,d3
;		  UR G U1U0 S CM M U W PDT
	or.w	#%00_1__00__0_00_0_0_0_11,d3
	movea.l	#$10000000,a1
	add.l	a1,d1
4:	move.l	a1,d2
	or.w	d3,d2
	bsr	setDesc
	bmi	9f			;エラー無視
	adda.l	(pageOffsetSize)r,a1
	cmpa.l	d1,a1
	bne	4b
5:

9:

;転送バッファの領域をライトスルーにする
	tst.l	(tempBufferSize)r
	beq	2f			;念のため
	movea.l	(tempBufferStart)r,a1	;既にページサイズに合わせてある
	movea.l	(tempBufferEnd)r,a2	;既にページサイズに合わせてある
1:	moveq.l	#0,d2			;ライトスルー
	bsr	sysStat_8004
	adda.l	(pageOffsetSize)r,a1
	cmpa.l	a2,a1
	blo	1b
2:

;ADPCMの転送バッファの領域をライトスルーにする
	movea.l	(adpcmBufferStart)r,a1	;既にページサイズに合わせてある
	moveq.l	#0,d2			;ライトスルー
	bsr	sysStat_8004		;1ページだけ

;メインメモリ上のRAMDISKの領域をノンキャッシャブルにする
	movea.l	(mainRamdiskAreaStart)r,a1
	movea.l	(mainRamdiskAreaEnd)r,a2
	cmpa.l	a1,a2
	beq	2f
1:	moveq.l	#3,d2			;キャッシュ禁止ストアバッファ許可
	bsr	sysStat_8004
;指定論理ページをスーパーバイザ保護する
;<a1.l:論理アドレス
	PUSH_MMU_SFC_DFC	d0
	bsr	getDesc
	bset.l	#PD_S_BIT,d0
	moves.l	d0,(a0)
	POP_SFC_DFC	d0
;
	adda.l	(pageOffsetSize)r,a1
	cmpa.l	a2,a1
	blo	1b
2:

;ローカルメモリ上のRAMDISKの領域をノンキャッシャブルにする
	movea.l	(localRamdiskAreaStart)r,a1
	movea.l	(localRamdiskAreaEnd)r,a2
	cmpa.l	a1,a2
	beq	2f
1:	moveq.l	#3,d2			;キャッシュ禁止ストアバッファ許可
	bsr	sysStat_8004
;指定論理ページをスーパーバイザ保護する
;<a1.l:論理アドレス
	PUSH_MMU_SFC_DFC	d0
	bsr	getDesc
	bset.l	#PD_S_BIT,d0
	moves.l	d0,(a0)
	POP_SFC_DFC	d0
;
	adda.l	(pageOffsetSize)r,a1
	cmpa.l	a2,a1
	blo	1b
2:

;ローカルメモリ上のROM
	tst.b	(localRomArea)r
	beq	2f
	movea.l	#$00F00000,a1
	move.l	(localRomStart)r,d2
1:	bsr	sysStat_F001		;ROMアドレス→ローカルメモリ
	exg.l	d2,a1
	bsr	invDesc			;ローカルメモリ→無効
	exg.l	d2,a1
	add.l	(pageOffsetSize)r,d2
	adda.l	(pageOffsetSize)r,a1
	cmp.l	#$01000000,a1
	blo	1b


2:

;デスクリプタの領域を見えなくする
	movea.l	(descAreaStart)r,a1
1:	bsr	invDesc
	adda.l	(pageOffsetSize)r,a1
	cmpa.l	(descAreaEnd)r,a1
	bne	1b
2:

	CACHE_FLUSH	d0		;念のためプッシュしておく
	rts

physicalModeTable::
;			   UR G U1U0 S CM M U W PDT
;	.dc.l	          %00_1__00__1_00_0_0_0_01	;Vector
;	.dc.l	$00002000
mainPD:
	.dc.l	          %00_1__00__0_00_0_0_0_01	;Main Memory
	.dc.l	$00C00000,%00_1__00__1_11_0_0_0_01	;Graphic
	.dc.l	$00E00000,%00_1__00__1_11_0_0_0_01	;Text
	.dc.l	$00E80000,%00_1__00__1_10_0_0_0_01	;CRTC
	.dc.l	$00E82000,%00_1__00__1_10_0_0_0_01	;Palet/Video Controler
	.dc.l	$00E84000,%00_1__00__1_10_0_0_0_01	;DMAC
	.dc.l	$00E86000,%00_1__00__1_10_0_0_0_01	;Supervisor Area Control
	.dc.l	$00E88000,%00_1__00__1_10_0_0_0_01	;MFP
	.dc.l	$00E8A000,%00_1__00__1_10_0_0_0_01	;RTC
	.dc.l	$00E8C000,%00_1__00__1_10_0_0_0_01	;Printer
	.dc.l	$00E8E000,%00_1__00__1_10_0_0_0_01	;System Port
	.dc.l	$00E90000,%00_1__00__1_10_0_0_0_01	;FM
	.dc.l	$00E92000,%00_1__00__1_10_0_0_0_01	;ADPCM
	.dc.l	$00E94000,%00_1__00__1_10_0_0_0_01	;FDC
	.dc.l	$00E96000,%00_1__00__1_10_0_0_0_01	;Internal SCSI
	.dc.l	$00E98000,%00_1__00__1_10_0_0_0_01	;SCC
	.dc.l	$00E9A000,%00_1__00__1_10_0_0_0_01	;Joy Stick
	.dc.l	$00E9C000,%00_1__00__1_10_0_0_0_01	;I/O Interrupt Control
	.dc.l	$00E9E000,%00_1__00__1_10_0_0_0_01	;Co-processor
	.dc.l	$00EA0000,%00_1__00__1_10_0_0_0_01	;External SCSI
	.dc.l	$00EAE000,%00_1__00__1_10_0_0_0_01	;Supervisor Area Control
							;External RS-232C
	.dc.l	$00EB0000,%00_1__00__1_10_0_0_0_01	;Sprite Register/Controler
	.dc.l	$00EB8000,%00_1__00__1_11_0_0_0_01	;Sprite PCG
	.dc.l	$00EBC000,%00_1__00__1_11_0_0_0_01	;Sprite Text
	.dc.l	$00EC0000,%00_1__00__0_10_0_0_0_01	;User I/O
	.dc.l	$00ED0000,%00_1__00__1_10_0_0_0_01	;SRAM
	.dc.l	$00ED4000,%00_1__00__0_10_0_0_0_01	;User I/O
	.dc.l	$00F00000,%00_1__00__1_00_0_0_1_01	;ROM
	.dc.l	-1

makeTranslationMain:
	.dc.b	'アドレス変換テーブルをメインメモリに配置します',13,10,0
	.even

;----------------------------------------------------------------
;アドレス変換を有効にする
enableTranslation::
	PUSH_SR_DI

	moveq.l	#0,d0
	movec.l	d0,cacr
	CACHE_FLUSH	d0

	move.l	(rootDescHead)r,d0
	movec.l	d0,srp
	movec.l	d0,urp

;		  E  P NAD NAI FOTC FITC DCO DUO DWO DCI DUI
	move.l	#%1__0__0__0___0____0____10__00__0___10__00_0,d0
	cmpi.l	#4096,(pageOffsetSize)r
	beq	@f
	bset.l	#TC_P_BIT,d0
@@:	movec.l	d0,tc

	pflusha

	POP_SR
	rts


;----------------------------------------------------------------
;パラメータの解釈
;<a0.l:ワードの先頭
getParam::
	movea.l	a0,a1
	cmpi.b	#'-',(a0)+
	bne	9f
	move.w	(a0)+,d0		;奇数アドレスの可能性がある
	or.w	#$2020,d0
	cmp.w	#'ad',d0
	beq	param_ad
	cmp.w	#'bg',d0
	beq	param_bg
	cmp.w	#'bs',d0
	beq	param_bs
	cmp.w	#'cm',d0
	beq	param_cm
	cmp.w	#'dv',d0
	beq	param_dv
	cmp.w	#'fe',d0
	beq	param_fe
	cmp.w	#'hi',d0
	beq	param_hi
	cmp.w	#'ld',d0
	beq	param_ld
	cmp.w	#'lr',d0
	beq	param_lr
	cmp.w	#'ls',d0
	beq	param_ls
	cmp.w	#'lt',d0
	beq	param_lt
	cmp.w	#'lz',d0
	beq	param_lz
	cmp.w	#'md',d0
	beq	param_md
	cmp.w	#'mm',d0
	beq	param_mm
	cmp.w	#'np',d0
	beq	param_np
	cmp.w	#'nt',d0
	beq	param_nt
	cmp.w	#'sd',d0
	beq	param_sd
	cmp.w	#'sl',d0
	beq	param_sl
	cmp.w	#'ss',d0
	beq	param_ss
	cmp.w	#'ts',d0
	beq	param_ts
	cmp.w	#'xm',d0
	beq	param_xm
9:	bsr	print
	lea.l	(1f,pc),a1
	bra	print
1:	.dc.b	' … 解釈できませんので無視します',13,10,0
	.even

;----------------------------------------------------------------
;文法:	-sl
;機能:	68060のstore/load bypass機能を有効にする
;説明:	68060のresult forwarding featuresの1つであるstore/load
;	bypass機能を有効にします。
;	store/load bypass機能はリセット直後は有効ですが、
;	060turbo.sys(v0.54以降)がこれを無効にしています。
;	-slを指定すると、store/load bypass機能が有効になります。
;	store/load bypass機能を無効にすることによる速度低下はほ
;	とんどありません。
param_sl:
	cmpi.b	#6,$0CBC.w
	bne	10f
	movec.l	pcr,d0
	bclr.l	#5,d0			;enable store/load bypass
	movec.l	d0,pcr
10:
	rts

;----------------------------------------------------------------
;文法:	-mm<size>
;	<size>	メインメモリのサイズ(単位は MB)
;機能:	メインメモリのサイズの設定
;説明:	メインメモリのサイズを指定します。
;	メモリが足りなければローカルメモリがあればそこから補い、
;	多すぎたらローカルメモリ側に押し出します。
;	メモリサイズの変更はシェル起動前に行われます。
;	-mm0 とするとデバイスドライバより後ろのメモリをすべて
;	ローカルメモリ側に押し出します(JUPITER の拡張モードと同じ)。
param_mm:
	tst.b	(noTranslation)r
	bne	param_mm_notrans	;-ntが指定されている
	bsr	stou
	bmi	param_mm_illegal
	cmp.l	#12,d0
	bhi	param_mm_illegal
	swap.w	d0
	lsl.l	#4,d0
	move.l	d0,(mainMemorySize)r
	rts

param_mm_notrans:
	lea.l	(@f,pc),a1
	bra	print
@@:	.dc.b	'-nt と -mm は同時に指定できません.-mm は無効です',13,10,0
	.even

param_mm_illegal:
	lea.l	(@f,pc),a1
	bra	print
@@:	.dc.b	'-mm の指定値が異常です',13,10,0
	.even

;----------------------------------------------------------------
;文法:	-ts<size>
;	<size>	アドレス変換のための領域のサイズ(単位は KB)
;機能:	アドレス変換のための領域のサイズの設定
;説明:	アドレス変換のための領域のサイズを指定します。
;	ページサイズが 8KB のとき、ローカルメモリの容量に応じた
;	最低サイズとデフォルトサイズは以下の通りです。
;					最低	デフォルト
;		本体16MBのみ		10KB	32KB
;		本体16MB+ローカル16MB	19KB	48KB
;		本体16MB+ローカル32MB	27KB	64KB
;		本体16MB+ローカル64MB	44KB	96KB
;		本体16MB+ローカル128MB	78KB	160KB
;		本体16MB+ローカル256MB	146KB	320KB
;		本体16MB+ローカル384MB	214KB	480KB
;		本体16MB+ローカル512MB	282KB	640KB
;		本体16MB+ローカル768MB	418KB	960KB
;	4MB 以上は指定できません。
param_ts:
	cmpi.b	#3,$0CBC.w
	beq	param_ts_68030		;68030では指定できない
	tst.b	(noTranslation)r
	bne	param_ts_notrans	;-ntが指定されている
	bsr	stou
	bmi	param_ts_illegal	;数字がない
	cmp.l	#4096,d0
	bhi	param_ts_toobig		;大きすぎる
	move.l	(localMemorySize)r,d1
	bne	@f
;本体16MBのみ
	cmp.w	#MINIMUM_DESC_SIZE_0>>10,d0
	blo	param_ts_toosmall	;小さすぎる
	bra	9f

@@:	cmp.l	#16<<20,d1
	bhi	@f
;本体16MB+ローカル16MB
	cmp.w	#MINIMUM_DESC_SIZE_16>>10,d0
	blo	param_ts_toosmall	;小さすぎる
	bra	9f

@@:	cmp.l	#32<<20,d1
	bhi	@f
;本体16MB+ローカル32MB
	cmp.w	#MINIMUM_DESC_SIZE_32>>10,d0
	blo	param_ts_toosmall	;小さすぎる
	bra	9f

@@:	cmp.l	#64<<20,d1
	bhi	@f
;本体16MB+ローカル64MB
	cmp.w	#MINIMUM_DESC_SIZE_64>>10,d0
	blo	param_ts_toosmall	;小さすぎる
	bra	9f

@@:	cmp.l	#128<<20,d1
	bhi	@f
;本体16MB+ローカル128MB
	cmp.w	#MINIMUM_DESC_SIZE_128>>10,d0
	blo	param_ts_toosmall	;小さすぎる
	bra	9f

@@:	cmp.l	#256<<20,d1
	bhi	@f
;本体16MB+ローカル256MB
	cmp.w	#MINIMUM_DESC_SIZE_256>>10,d0
	blo	param_ts_toosmall	;小さすぎる
	bra	9f

@@:	cmp.l	#384<<20,d1
	bhi	@f
;本体16MB+ローカル384MB
	cmp.w	#MINIMUM_DESC_SIZE_384>>10,d0
	blo	param_ts_toosmall	;小さすぎる
	bra	9f

@@:	cmp.l	#512<<20,d1
	bhi	@f
;本体16MB+ローカル512MB
	cmp.w	#MINIMUM_DESC_SIZE_512>>10,d0
	blo	param_ts_toosmall	;小さすぎる
	bra	9f

@@:
;本体16MB+ローカル768MB
	cmp.w	#MINIMUM_DESC_SIZE_768>>10,d0
	blo	param_ts_toosmall	;小さすぎる

9:	lsl.l	#8,d0
	lsl.l	#2,d0
	move.l	d0,(descAreaSize)r
	rts

param_ts_68030:
	lea.l	(@f,pc),a1
	bra	print
@@:	.dc.b	'-ts は 68030 では指定できません.-ts は無効です',13,10,0
	.even

param_ts_notrans:
	lea.l	(@f,pc),a1
	bra	print
@@:	.dc.b	'-nt と -ts は同時に指定できません.-ts は無効です',13,10,0
	.even

param_ts_toosmall:
	lea.l	(@f,pc),a1
	bra	print
@@:	.dc.b	'-ts の指定値が小さすぎます。デフォルトを使用します',13,10,0
	.even

param_ts_toobig:
	lea.l	(@f,pc),a1
	bra	print
@@:	.dc.b	'-ts の指定値が大きすぎます。デフォルトを使用します',13,10,0
	.even

param_ts_illegal:
	lea.l	(@f,pc),a1
	bra	print
@@:	.dc.b	'-ts の指定値が異常です。デフォルトを使用します',13,10,0
	.even

;----------------------------------------------------------------
;文法:	-lr
;説明:	ローカルメモリがあるとき、ROM をローカルメモリにコピーし
;	て使います。
param_lr:
	tst.b	(localRomArea)r
	bne	99f			;-lrは既に指定された
	tst.b	(forceNoSimm)r
	bne	param_lr_nosimm		;-lzが指定されている
	cmpi.b	#3,$0CBC.w
	beq	param_lr_68030		;68030では指定できない
	tst.b	(noTranslation)r
	bne	param_lr_notrans	;-ntが指定されている
	tst.l	(localMemorySize)r
	beq	param_lr_cannot		;ローカルメモリがない
	move.l	(localUpperStart)r,d0
	sub.l	#1024*1024,d0
	cmp.l	(localLowerEnd)r,d0
	blo	param_lr_over
	move.l	d0,(localUpperStart)r
	move.l	d0,(localRomStart)r
	add.l	#1024*1024,d0
	move.l	d0,(localRomEnd)r
	st.b	(localRomArea)r
99:	rts

param_lr_nosimm:
	lea.l	(@f,pc),a1
	bra	print
@@:	.dc.b	'-lz と -lr は同時に指定できません.-lr は無効です',13,10,0
	.even

param_lr_68030:
	lea.l	(@f,pc),a1
	bra	print
@@:	.dc.b	'-lr は 68030 では指定できません.-lr は無効です',13,10,0
	.even

param_lr_notrans:
	lea.l	(@f,pc),a1
	bra	print
@@:	.dc.b	'-nt と -lr は同時に指定できません.-lr は無効です',13,10,0
	.even

param_lr_over:
	lea.l	(@f,pc),a1
	bra	print
@@:	.dc.b	'ローカルメモリが不足しています.-lr は無効です',13,10,0
	.even

param_lr_cannot:
	lea.l	(@f,pc),a1
	bra	print
@@:	.dc.b	'ローカルメモリがありません.-lr は無効です',13,10,0
	.even

;----------------------------------------------------------------
;文法:	-lt
;説明:	ローカルメモリがあるとき、アドレス変換テーブルをローカル
;	メモリに置きます。
param_lt:
	tst.b	(forceNoSimm)r
	bne	param_lt_nosimm		;-lzが指定されている
	cmpi.b	#3,$0CBC.w
	beq	param_lt_68030		;68030では指定できない
	tst.b	(noTranslation)r
	bne	param_lt_notrans	;-ntが指定されている
	tst.l	(localMemorySize)r
	beq	9f
	st.b	(localAreaDescriptor)r
	rts

param_lt_nosimm:
	lea.l	(@f,pc),a1
	bra	print
@@:	.dc.b	'-lz と -lt は同時に指定できません.-lt は無効です',13,10,0
	.even

param_lt_68030:
	lea.l	(@f,pc),a1
	bra	print
@@:	.dc.b	'-lt は 68030 では指定できません.-lt は無効です',13,10,0
	.even

param_lt_notrans:
	lea.l	(@f,pc),a1
	bra	print
@@:	.dc.b	'-nt と -lt は同時に指定できません.-lt は無効です',13,10,0
	.even

9:	lea.l	(@f,pc),a1
	bra	print
@@:	.dc.b	'ローカルメモリがありません.-lt は無効です',13,10,0
	.even

;----------------------------------------------------------------
;文法:	-ss
;機能:	SCSI のアクセスでソフト転送を使う
;説明:	IOCS $F5 による SCSI のアクセスでローカルメモリとのやりと
;	りを可能にします。
;	指定されたバッファの論理アドレスが物理アドレスと異なって
;	いたり、実体がローカルメモリにあるとき、一時的にソフト転
;	送に切り替えます。
param_ss:
	st.b	(patchIocsScsi)r
	rts

;----------------------------------------------------------------
;文法:	-dv
;機能:	デバイスドライバのアクセスでテンポラリバッファを使う
;説明:	デバイスドライバのアクセスでローカルメモリとのやりとりを
;	可能にします。
;	指定されたバッファの論理アドレスが物理アドレスと異なって
;	いたり、実体がローカルメモリにあるとき、テンポラリバッフ
;	ァを媒介してデータをやりとりします。
param_dv:
	st.b	(patchDevice)r
	rts

;----------------------------------------------------------------
;文法:	-bs<size>
;	<size>	テンポラリバッファのサイズ(単位は KB)
;説明:	-dv 指定時に使用するテンポラリバッファのサイズを指定しま
;	す。デフォルトは 64KB です。
;	テンポラリバッファは常にメインメモリ上に確保されます。
param_bs:
	tst.l	(tempBufferSize)r
	bne	param_bs_already
	bsr	stou
	bmi	param_bs_illegal
	lsl.l	#8,d0
	lsl.l	#2,d0
	add.l	#$00001FFF,d0		;転送バッファはページ位置に合わせる
	and.l	#$FFFFE000,d0
	move.l	d0,(tempBufferSize)r
	move.l	(mainLowerEnd)r,d1
	add.l	#$00001FFF,d1		;転送バッファはページ位置に合わせる
	and.l	#$FFFFE000,d1
	move.l	d1,(tempBufferStart)r
	add.l	d0,d1
	move.l	d1,(tempBufferEnd)r
	move.l	d1,d0
	add.l	#128*1024,d0
	cmp.l	(mainUpperStart)r,d0
	bhi	param_bs_over
	move.l	d1,(mainLowerEnd)r
	rts

param_bs_already:
	lea.l	(@f,pc),a1
	bra	9f
@@:	.dc.b	'-bs は二重指定です',13,10,0
	.even

param_bs_illegal:
	lea.l	(@f,pc),a1
	bra	9f
@@:	.dc.b	'-bs の指定が異常です',13,10,0
	.even

param_bs_over:
	lea.l	(@f,pc),a1
9:	bsr	print
	clr.l	(tempBufferSize)r
	rts
@@:	.dc.b	'-bs の指定が大きすぎます.デフォルトを使用します',13,10,0
	.even

;----------------------------------------------------------------
;文法:	-xm
;機能:	拡張モードの設定
;説明:	拡張モードにしてからシェルを起動します。
;	Human のメモリ管理をローカルメモリまで拡張します。
;	メモリ管理関係の DOS コールを拡張します。
;	XC のライブラリを使用しているプログラムをロードしたとき、
;	自動的にパッチをあてます。
param_xm:
	tst.b	(forceNoSimm)r
	bne	param_xm_nosimm		;-lzが指定されている
	tst.l	(localMemorySize)r
	beq	9f
	st.b	(useJointMode)r
	st.b	(jointMode)r
	rts

param_xm_nosimm:
	lea.l	(@f,pc),a1
	bra	print
@@:	.dc.b	'-lz と -xm は同時に指定できません.-xm は無効です',13,10,0
	.even

9:	lea.l	(@f,pc),a1
	bra	print
@@:	.dc.b	'ローカルメモリがありません.-xm は無効です',13,10,0
	.even

;----------------------------------------------------------------
;文法:	-hi
;	v0.53より完全に廃止
param_hi:
	rts

;----------------------------------------------------------------
;文法:	-md<size>{[K]|M}[a][i]
;	<size>	RAMDISK のサイズ
;	K	サイズの単位は KB
;	M	サイズの単位は MB
;	a	TIMER-LED をアクセスランプにする
;	i	SHIFT キーが押されていないとき初期化する
;機能:	メインメモリ上の RAMDISK の設定
;説明:	RAMDISK ドライバを組み込みます。RAMDISK の領域はメインメ
;	モリの上位側から確保されます。
;	<size> の範囲は 16KB から 32767KB までです。ただし、メイ
;	ンメモリの容量によって制限されます。
;	i を指定しなければ SHIFT キーが押されているとき初期化し
;	ます。ただし、RAMDISK の先頭が壊れているときは無条件に初
;	期化します。
;	-ld と -md は合わせて 16 個まで指定できます。
;	RAMDISK の領域はスーパーバイザプロテクトされます。また、
;	キャッシュモードをノンキャッシャブル・インプリサイズドシ
;	リアライゼーションにすることで、キャッシュを無駄遣いしな
;	いようにします。
;例:	-md512Ka
;		メインメモリ上に 512KB の RAMDISK を確保します。
;		TIMER-LED をアクセスランプにします。
;		SHIFT キーが押されているとき初期化します。
;<a0.l:'md'の次のアドレス
param_md:
	moveq.l	#0,d0
	move.b	(unitCounter)r,d0
	cmp.b	#MAXIMUM_UNIT,d0
	beq	param_md_toomany	;ユニット数が多すぎる
	lea.l	(bpbTablePointer)r,a1
1:	movea.l	(a1)+,a3
	dbra	d0,1b
;<a3.l:BPBテーブル
	moveq.l	#0,d2
	cmpi.b	#'-',(a0)
	bne	@f
	moveq.l	#1,d2
	addq.l	#1,a0
@@:	bsr	stou
	bmi	param_md_illegal
	move.l	d0,d1
	moveq.l	#$20,d0
	or.b	(a0),d0
	cmp.b	#'k',d0
	beq	1f
	cmp.b	#'m',d0
	bne	2f
	lsl.l	#8,d1
	lsl.l	#2,d1
1:	addq.l	#1,a0
2:	tst.l	d2
	beq	@f
	move.l	(mainUpperStart)r,d0
	sub.l	(mainLowerEnd)r,d0
	lsr.l	#8,d0
	lsr.l	#2,d0
	sub.l	d1,d0
	move.l	d0,d1
@@:	cmp.l	#MINIMUM_SIZE,d1
	blo	param_md_illegal
	cmp.l	#MAXIMUM_SIZE,d1
	bhi	param_md_illegal
;<d1.l:全領域のセクタ数
	move.l	d1,(12,a3)		;全領域のセクタ数
	move.l	d1,d2
	lsl.l	#8,d2
	lsl.l	#2,d2			;全領域のバイト数
;<d2.l:全領域のバイト数
;メインメモリのRAMDISKは末尾から確保する
	movea.l	(mainRamdiskAreaStart)r,a1
;<a1.l:末尾アドレス+1
	movea.l	a1,a2
	suba.l	d2,a2
;<a2.l:先頭アドレス
	move.l	a2,d0
	sub.l	#128*1024,d0
	cmp.l	(mainLowerEnd)r,d0
	blt	param_md_over
	move.l	a2,(mainRamdiskAreaStart)r
;<a1.l:末尾アドレス+1
;<a2.l:先頭アドレス
	move.l	a2,(16,a3)		;先頭アドレス
	move.l	a1,(20,a3)		;末尾アドレス+1
	moveq.l	#0,d6
1:	move.b	(a0)+,d0
	beq	2f
	or.b	#$20,d0
	cmp.b	#'i',d0
	bne	@f
	or.b	#%00000001,d6
	bra	1b
@@:	cmp.b	#'a',d0
	bne	@f
	or.b	#%00000100,d6
	bra	1b
@@:	bra	param_md_illegal
2:
;<d1.l:全領域のセクタ数
	move.l	d1,d0
	sub.l	#(ROOT_ENTRY+31)>>5,d0
;<d0.l:データ領域のセクタ数の上限
	moveq.l	#1,d3
	moveq.l	#0,d4
	bra	2f
1:	add.l	d3,d3			;1クラスタあたりのセクタ数
	addq.l	#1,d4			;1クラスタあたりのセクタ数のシフトカウント
	lsr.l	#1,d0
2:	cmp.l	#$0000FFF0,d0
	bhi	1b
	addq.l	#2,d0
;<d0.l:データ領域のクラスタ数の上限+2
;<d3.l:1クラスタあたりのセクタ数
;<d4.l:1クラスタあたりのセクタ数のシフトカウント
	move.b	d3,(2,a3)		;1クラスタあたりのセクタ数
	move.l	d0,d3
	add.l	d3,d3
	cmp.l	#$0FF7,d0
	bcc	@f
	lsr.l	#2,d3
	addx.l	d0,d3
@@:	add.l	#$03FF,d3
	lsr.l	#8,d3
	lsr.l	#2,d3
;<d3.l:FAT領域のセクタ数
	move.b	d3,(11,a3)		;1個のFAT領域に使用するセクタ数
	move.l	d1,d5			;全領域のセクタ数
	sub.l	#(ROOT_ENTRY+31)>>5,d5
	sub.l	d3,d5
;<d5.l:データ領域のセクタ数
	lsr.l	d4,d5
	addq.l	#2,d5
;<d5.l:データ領域のクラスタ数+2
	moveq.l	#1,d4
	cmpi.w	#$F9FF,(a2)
	bne	1f			;壊れている
	cmpi.b	#$FF,(2,a2)
	bne	1f			;壊れている
	IOCS	_B_SFTSNS
	and.b	d0,d4			;SHIFTキーの状態
	btst.l	#0,d6
	beq	@f			;初期化指定がない
	eori.b	#1,d4			;SHIFTキーの条件を反転する
@@:	tst.l	d4
	beq	2f			;初期化しない
1:	movea.l	a2,a0			;先頭アドレス
	move.l	d3,d0			;1個のFAT領域に使用するセクタ数
	lsl.l	#10-2,d0		;1個のFAT領域に使用するバイト数/4
	subq.w	#1,d0
@@:	clr.l	(a0)+			;FATを初期化
	dbra	d0,@b
	move.w	#ROOT_ENTRY*32/4-1,d0
@@:	clr.l	(a0)+			;ルートディレクトリを初期化
	dbra	d0,@b
	moveq.l	#$F9,d0
	ror.l	#8,d0
	cmp.l	#$00000FF7,d5
	bcc	@f
	clr.b	d0
@@:	move.l	d0,(a2)			;FATのヘッダをセット
2:
;<d4.l:初期化フラグ(0=初期化しなかった,1=初期化した)
;アクセスランプ
	btst.l	#2,d6
	sne.b	(24,a3)
;メッセージ表示
	lea.l	(param_md_message,pc),a1
	moveq.l	#'A',d0
	add.b	(22,a5),d0		;ドライブ名
	add.b	(unitCounter)r,d0
	move.b	d0,(param_md_drive-param_md_message,a1)
	move.l	a2,d0
	lea.l	(param_md_start-param_md_message,a1),a0
	bsr	hex8			;整数→16進数8桁
	add.l	d2,d0
	subq.l	#1,d0
	lea.l	(param_md_end-param_md_message,a1),a0
	bsr	hex8			;整数→16進数8桁
	bsr	print
	lea.l	(param_md_not_initialized,pc),a1	;'は初期化しません'
	tst.l	d4
	beq	@f
	lea.l	(param_md_initialized,pc),a1	;'を初期化しました'
@@:	bsr	print
;
	addq.b	#1,(unitCounter)r
	rts

param_md_message:
	.dc.b	'RAMディスク '
param_md_drive:
	.dc.b	'?: $'
param_md_start:
	.dc.b	'xxxxxxxx~$'
param_md_end:
	.dc.b	'xxxxxxxx ',0
param_md_not_initialized:
	.dc.b	'は初期化しません',13,10,0
param_md_initialized:
	.dc.b	'を初期化しました',13,10,0
	.even

param_md_toomany:
	lea.l	(@f,pc),a1
	bra	print
@@:	.dc.b	'-md のユニット数が多すぎます',13,10,0
	.even

param_md_illegal:
	lea.l	(@f,pc),a1
	bra	print
@@:	.dc.b	'-md の指定が異常です',13,10,0
	.even

param_md_over:
	lea.l	(@f,pc),a1
	bra	print
@@:	.dc.b	'-md の指定が大きすぎます',13,10,0
	.even

;----------------------------------------------------------------
;文法:	-ld<size>{[K]|M}[a][i]
;	<size>	RAMDISK のサイズ
;	K	<size> の単位は KB
;	M	<size> の単位は MB
;	a	TIMER-LED をアクセスランプにする
;	i	SHIFT キーが押されていないとき初期化する
;機能:	ローカルメモリ上の RAMDISK の設定
;説明:	RAMDISK ドライバを組み込みます。RAMDISK の領域はローカル
;	メモリの下位側から確保されます。
;	<size> の範囲は 16KB から 1024MB までです。ただし、ロー
;	カルメモリの容量によって制限されます。
;	<size> に - を付けると残すサイズを指定できます。
;	i を指定しなければ SHIFT キーが押されているとき初期化し
;	ます。ただし、RAMDISK の先頭が壊れているときは無条件に初
;	期化します。
;	-ld と -md は合わせて 16 個まで指定できます。
;	RAMDISK の領域はスーパーバイザプロテクトされます。また、
;	キャッシュモードをノンキャッシャブル・インプリサイズドシ
;	リアライゼーションにすることで、キャッシュを無駄遣いしな
;	いようにします。
;例:	-ld16Mai
;		ローカルメモリ上に 16MB の RAMDISK を確保します。
;		TIMER-LED をアクセスランプにします。
;		SHIFT キーが押されていないとき初期化します。
;<a0.l:'ld'の次のアドレス
param_ld:
	tst.b	(forceNoSimm)r
	bne	param_ld_nosimm		;-lzが指定されている
	tst.l	(localMemorySize)r
	beq	param_ld_cannot		;ローカルメモリがない
	moveq.l	#0,d0
	move.b	(unitCounter)r,d0
	cmp.b	#MAXIMUM_UNIT,d0
	beq	param_ld_toomany	;ユニット数が多すぎる
	lea.l	(bpbTablePointer)r,a1
1:	movea.l	(a1)+,a3
	dbra	d0,1b
;<a3.l:BPBテーブル
	moveq.l	#0,d2
	cmpi.b	#'-',(a0)
	bne	@f
	moveq.l	#1,d2
	addq.l	#1,a0
@@:	bsr	stou
	bmi	param_ld_illegal
	move.l	d0,d1
	moveq.l	#$20,d0
	or.b	(a0),d0
	cmp.b	#'k',d0
	beq	1f
	cmp.b	#'m',d0
	bne	2f
	lsl.l	#8,d1
	lsl.l	#2,d1
1:	addq.l	#1,a0
2:	tst.l	d2
	beq	@f
	move.l	(localUpperStart)r,d0
	sub.l	(localRamdiskAreaEnd)r,d0
	lsr.l	#8,d0
	lsr.l	#2,d0
	sub.l	d1,d0			;確保するセクタ数=空きセクタ数-残すセクタ数
	move.l	d0,d1
@@:	cmp.l	#MINIMUM_SIZE,d1
	blo	param_ld_illegal
	cmp.l	#MAXIMUM_SIZE,d1
	bhi	param_ld_illegal
;<d1.l:全領域のセクタ数
	move.l	d1,(12,a3)		;全領域のセクタ数
	move.l	d1,d2
	lsl.l	#8,d2
	lsl.l	#2,d2			;全領域のバイト数
;ハイメモリのRAMDISKは先頭から確保する
;<d2.l:全領域のバイト数
	movea.l	(localRamdiskAreaEnd)r,a2
;<a2.l:先頭アドレス
	lea.l	(a2,d2.l),a1
;<a1.l:末尾アドレス+1
	cmpa.l	(localUpperStart)r,a1
	bhi	param_ld_over		;残り0を許容している。-xmができなくなる
	move.l	a1,(localRamdiskAreaEnd)r
;<a1.l:末尾アドレス+1
;<a2.l:先頭アドレス
	move.l	a2,(16,a3)		;先頭アドレス
	move.l	a1,(20,a3)		;末尾アドレス+1
	moveq.l	#0,d6
1:	move.b	(a0)+,d0
	beq	2f
	or.b	#$20,d0
	cmp.b	#'i',d0
	bne	@f
	or.b	#%00000001,d6
	bra	1b
@@:	cmp.b	#'a',d0
	bne	@f
	or.b	#%00000100,d6
	bra	1b
@@:	bra	param_ld_illegal
2:
;<d1.l:全領域のセクタ数
	move.l	d1,d0
	sub.l	#(ROOT_ENTRY+31)>>5,d0
;<d0.l:データ領域のセクタ数の上限
	moveq.l	#1,d3
	moveq.l	#0,d4
	bra	2f
1:	add.l	d3,d3			;1クラスタあたりのセクタ数
	addq.l	#1,d4			;1クラスタあたりのセクタ数のシフトカウント
	lsr.l	#1,d0
2:	cmp.l	#$0000FFF0,d0
	bhi	1b
	addq.l	#2,d0
;<d0.l:データ領域のクラスタ数の上限+2
;<d3.l:1クラスタあたりのセクタ数
;<d4.l:1クラスタあたりのセクタ数のシフトカウント
	move.b	d3,(2,a3)		;1クラスタあたりのセクタ数
	move.l	d0,d3
	add.l	d3,d3
	cmp.l	#$0FF7,d0
	bcc	@f
	lsr.l	#2,d3
	addx.l	d0,d3
@@:	add.l	#$03FF,d3
	lsr.l	#8,d3
	lsr.l	#2,d3
;<d3.l:FAT領域のセクタ数
	move.b	d3,(11,a3)		;1個のFAT領域に使用するセクタ数
	move.l	d1,d5			;全領域のセクタ数
	sub.l	#(ROOT_ENTRY+31)>>5,d5
	sub.l	d3,d5
;<d5.l:データ領域のセクタ数
	lsr.l	d4,d5
	addq.l	#2,d5
;<d5.l:データ領域のクラスタ数+2
	moveq.l	#1,d4
	cmpi.w	#$F9FF,(a2)
	bne	1f			;壊れている
	cmpi.b	#$FF,(2,a2)
	bne	1f			;壊れている
	IOCS	_B_SFTSNS
	and.b	d0,d4			;SHIFTキーの状態
	btst.l	#0,d6
	beq	@f			;初期化指定がない
	eori.b	#1,d4			;SHIFTキーの条件を反転する
@@:	tst.l	d4
	beq	2f			;初期化しない
1:	movea.l	a2,a0			;先頭アドレス
	move.l	d3,d0			;1個のFAT領域に使用するセクタ数
	lsl.l	#10-2,d0		;1個のFAT領域に使用するバイト数/4
	subq.w	#1,d0
@@:	clr.l	(a0)+			;FATを初期化
	dbra	d0,@b
	move.w	#ROOT_ENTRY*32/4-1,d0
@@:	clr.l	(a0)+			;ルートディレクトリを初期化
	dbra	d0,@b
	moveq.l	#$F9,d0
	ror.l	#8,d0
	cmp.l	#$00000FF7,d5
	bcc	@f
	clr.b	d0
@@:	move.l	d0,(a2)			;FATのヘッダをセット
2:
;<d4.l:初期化フラグ(0=初期化しなかった,1=初期化した)
;アクセスランプ
	btst.l	#2,d6
	sne.b	(24,a3)
;メッセージ表示
	lea.l	(param_ld_message,pc),a1
	moveq.l	#'A',d0
	add.b	(22,a5),d0		;ドライブ名
	add.b	(unitCounter)r,d0
	move.b	d0,(param_ld_drive-param_ld_message,a1)
	move.l	a2,d0
	lea.l	(param_ld_start-param_ld_message,a1),a0
	bsr	hex8			;整数→16進数8桁
	add.l	d2,d0
	subq.l	#1,d0
	lea.l	(param_ld_end-param_ld_message,a1),a0
	bsr	hex8			;整数→16進数8桁
	bsr	print
	lea.l	(param_ld_not_initialized,pc),a1	;'は初期化しません'
	tst.l	d4
	beq	@f
	lea.l	(param_ld_initialized,pc),a1	;'を初期化しました'
@@:	bsr	print
;
	addq.b	#1,(unitCounter)r
	rts

param_ld_message:
	.dc.b	'RAMディスク '
param_ld_drive:
	.dc.b	'?: $'
param_ld_start:
	.dc.b	'xxxxxxxx~$'
param_ld_end:
	.dc.b	'xxxxxxxx ',0
param_ld_not_initialized:
	.dc.b	'は初期化しません',13,10,0
param_ld_initialized:
	.dc.b	'を初期化しました',13,10,0
	.even

param_ld_nosimm:
	lea.l	(@f,pc),a1
	bra	print
@@:	.dc.b	'-lz と -ld は同時に指定できません.-ld は無効です',13,10,0
	.even

param_ld_cannot:
	lea.l	(@f,pc),a1
	bra	print
@@:	.dc.b	'ローカルメモリがありません.-ld は無効です',13,10,0
	.even

param_ld_toomany:
	lea.l	(@f,pc),a1
	bra	print
@@:	.dc.b	'-ld のユニット数が多すぎます',13,10,0
	.even

param_ld_illegal:
	lea.l	(@f,pc),a1
	bra	print
@@:	.dc.b	'-ld の指定が異常です',13,10,0
	.even

param_ld_over:
	lea.l	(@f,pc),a1
	bra	print
@@:	.dc.b	'-ld の指定が大きすぎます',13,10,0
	.even

;----------------------------------------------------------------
;文法:	-cm<mode>
;	<mode>	キャッシュモード
;		0	キャッシュ許可,ライトスルー
;		1	キャッシュ許可,コピーバック
;		2	キャッシュ禁止,ストアバッファ禁止
;		3	キャッシュ禁止,ストアバッファ許可
;説明:	メモリのキャッシュモードを指定します。デフォルトはライト
;	スルーです。
param_cm:
	moveq.l	#0,d0
	move.b	(a0),d0
	sub.b	#'0',d0
	bmi	param_cm_illegal
	cmp.b	#3,d0
	bhi	param_cm_illegal
	move.b	d0,mainMemoryCacheMode
	move.b	d0,localMemoryCacheMode
	lsl.l	#PD_CM_BIT,d0
	andi.l	#.not.PD_CM_MASK,mainPD
	or.l	d0,mainPD
	rts

param_cm_illegal:
	lea.l	(@f,pc),a1
	bra	print
@@:	.dc.b	'-cm の指定が異常です',13,10,0
	.even

;----------------------------------------------------------------
;文法:	-bg
;説明:	スレッド間の排他制御を行います。
;	-bgを指定すると、スレッドが切り替わる度に、FPUの内部状態
;	と各レジスタ、標準ハンドラ、標準ハンドラの変換状態、各ド
;	ライブのカレントディレクトリ、カレントドライブが切り替わ
;	ります。
;	CONFIG.SYSのFILESの値は最低でも30以上を指定して下さい。
param_bg:
	tst.b	(backgroundFlag)r
	bne	99f			;-bgは既に指定された
	tst.w	$1C58.w			;processのスレッド数-1
	beq	param_bg_no_process	;サブスレッドは使えない
	cmpi.w	#30+2,$1C6E.w		;filesが30以上か
	blo	param_bg_no_files	;filesの指定値が小さすぎる
	movea.l	(mainLowerEnd)r,a1	;排他制御情報の先頭
	move.l	a1,(exclusiveStart)r
	move.w	#xSize2,d0		;排他制御情報1個のサイズ
	mulu.w	$1C58.w,d0		;サブスレッドの排他制御情報のサイズ
	add.l	#$0000000F,d0		;16の倍数に切り上げる
	and.l	#$FFFFFFF0,d0
	adda.l	d0,a1			;排他制御情報の末尾+1
	move.l	(mainUpperStart)r,d0
	sub.l	#128*1024,d0
	cmpa.l	d0,a1
	bhi	param_bg_over
	move.l	a1,(exclusiveEnd)r
	move.l	a1,(mainLowerEnd)r
	st.b	(backgroundFlag)r
99:	rts

param_bg_no_process:
	lea.l	(@f,pc),a1
	bra	print
@@:	.dc.b	'process が指定されていません.-bg は無効です',13,10,0
	.even

param_bg_no_files:
	lea.l	(@f,pc),a1
	bra	print
@@:	.dc.b	'files の指定値が小さすぎます.-bg は無効です',13,10,0
	.even

param_bg_over:
	lea.l	(@f,pc),a1
	bra	print
@@:	.dc.b	'メモリが不足しています.-bg は無効です',13,10,0
	.even

;----------------------------------------------------------------
;文法:	-sd
;説明:	IOCSによるDMA転送をソフト転送にします。
param_sd:
	st.b	(softwareIocsDma)r
	rts

;----------------------------------------------------------------
;文法:	-fe
;説明:	060turbo.sysの内部のFEファンクションを使用することを明示
;	します。後からFLOATn.Xを組み込むことができなくなります。
param_fe:
	cmpi.b	#6,$0CBC.w
	bne	param_fe_not_68060	;68060以外では指定できない
	move.l	#'FEfn',_060_fpsp_fline-4
	rts

param_fe_not_68060:
	lea.l	(@f,pc),a1
	bra	print
@@:	.dc.b	'-fe は 68060 以外では指定できません.-fe は無効です',13,10,0
	.even

;----------------------------------------------------------------
;文法:	-ls
;説明:	ベクタ領域からHuman本体の末尾までと060turbo.sys本体をロー
;	カルメモリにコピーして使います。
param_ls:
	tst.b	(localSystemArea)r
	bne	99f			;-lsは既に指定された
	tst.b	(forceNoSimm)r
	bne	param_ls_nosimm		;-lzが指定されている
	cmpi.b	#3,$0CBC.w
	beq	param_ls_68030		;68030では指定できない
	tst.b	(noTranslation)r
	bne	param_ls_notrans	;-ntが指定されている
	tst.l	(localMemorySize)r
	beq	param_ls_cannot
;システムをコピーする領域を確保
	move.l	#keepTail,d1
	and.l	#PAGE_MASK,d1		;変換する部分の末尾なので切り捨てる
	sub.l	#deviceHeader,d1
	and.l	#PAGE_MASK,d1		;060turbo.sysの常駐部分の長さ
	add.l	#$0001447A.and.PAGE_MASK,d1	;Humanの長さ
	move.l	(localUpperStart)r,d0
	sub.l	d1,d0
	cmp.l	(localLowerEnd)r,d0
	blo	param_ls_over
	move.l	d0,(localUpperStart)r
	move.l	d0,(localSystemStart)r
	add.l	d1,d0
	move.l	d0,(localSystemEnd)r
	st.b	(localSystemArea)r
99:	rts

param_ls_nosimm:
	lea.l	(@f,pc),a1
	bra	print
@@:	.dc.b	'-lz と -ls は同時に指定できません.-ls は無効です',13,10,0
	.even

param_ls_68030:
	lea.l	(@f,pc),a1
	bra	print
@@:	.dc.b	'-ls は 68030 では指定できません.-ls は無効です',13,10,0
	.even

param_ls_notrans:
	lea.l	(@f,pc),a1
	bra	print
@@:	.dc.b	'-nt と -ls は同時に指定できません.-ls は無効です',13,10,0
	.even

param_ls_over:
	lea.l	(@f,pc),a1
	bra	print
@@:	.dc.b	'ローカルメモリが不足しています.-ls は無効です',13,10,0
	.even

param_ls_cannot:
	lea.l	(@f,pc),a1
	bra	print
@@:	.dc.b	'ローカルメモリがありません.-ls は無効です',13,10,0
	.even

;----------------------------------------------------------------
;文法:	-np
;説明:	初期化以外のデバイス呼び出しでデータキャッシュのプッシュ
;	および無効化を行いません。
;	SCSI転送は強制的にソフト転送になります。
param_np:
	tst.b	(deviceCacheNoPush)r
	bne	99f				;-npは既に指定された
	st.b	(patchIocsScsi)r		;SCSIを強制的にソフト転送にする
	st.b	(forceSoftScsi)r
	st.b	([$1C20.w],pDeviceNoPush)	;Humanは-npを許可する
	st.b	(deviceCacheNoPush)r
99:	rts

;----------------------------------------------------------------
;文法:	-ad
;説明:	ADPCM関係のIOCSコールにパッチをあててローカルメモリから直
;	接再生できるようにします。
param_ad:
	st.b	(patchIocsAdpcm)r
	rts

;----------------------------------------------------------------
;文法:	-lz
;説明:	SIMMが装着されていても使わないことにします。
param_lz:
	tst.b	(forceNoSimm)r
	bne	99f			;-lzは既に指定された
	tst.l	(localMemorySize)r
	beq	99f			;ローカルメモリがない
	tst.l	(localRamdiskAreaSize)r
	bne	param_lz_error
	tst.b	(localAreaDescriptor)r
	bne	param_lz_error
	tst.b	(localRomArea)r
	bne	param_lz_error
	tst.b	(useJointMode)r
	bne	param_lz_error
	tst.b	(jointMode)r
	bne	param_lz_error
	tst.b	(localSystemArea)r
	bne	param_lz_error
	clr.l	(localMemorySize)r
	move.l	(localMemoryStart)r,(localMemoryEnd)r
	clr.l	(localLowerStart)r
	clr.l	(localLowerEnd)r
	clr.l	(localUpperStart)r
	clr.l	(localUpperEnd)r
	clr.l	(localRamdiskAreaStart)r
	clr.l	(localRamdiskAreaEnd)r
	st.b	(forceNoSimm)r
99:	rts

param_lz_error:
	lea.l	(@f,pc),a1
	bra	print
@@:	.dc.b	'-ld,-lr,-ls,-lt,-xm と -lz は同時に指定できません.-lz は無効です',13,10,0
	.even

;----------------------------------------------------------------
;文法:	-nt
;説明:	アドレス変換を行いません。
;	実機および実機と同じ手順でキャッシュラインを充填しようと
;	するエミュレータでは指定しないでください。
;	-lr,-ls,-lt,-mm,-ts と -nt は同時に指定できません。
param_nt:
	tst.b	(noTranslation)r
	bne	99f			;-ntは既に指定された(68030を含む)
	tst.b	(localRomArea)r
	bne	param_nt_error		;-lrが指定されている
	tst.b	(localSystemArea)r
	bne	param_nt_error		;-lsが指定されている
	tst.b	(localAreaDescriptor)r
	bne	param_nt_error		;-ltが指定されている
	tst.l	(mainMemorySize)r
	bpl	param_nt_error		;-mmが指定されている
	tst.l	(descAreaSize)r
	bne	param_nt_error		;-tsが指定されている
	st.b	(noTranslation)r
99:	rts

param_nt_error:
	lea.l	(@f,pc),a1
	bra	print
@@:	.dc.b	'-lr,-ls,-lt,-mm,-ts と -nt は同時に指定できません.-nt は無効です',13,10,0
	.even

;----------------------------------------------------------------
;文字列を符号なし10進数と見なして数値に変換する
;<a0.l:文字列のアドレス
;>d0.l:数値(0~$7FFFFFFF,-1=エラー)
;>a0.l:数字の次のアドレス
;>n-flag:mi=エラー
stou::
	move.l	d1,-(sp)
	moveq.l	#0,d0
	moveq.l	#0,d1
1:	move.b	(a0)+,d1
	sub.b	#'0',d1
	bcs	3f
	cmp.b	#10,d1
	bcc	3f
	mulu.l	#10,d0
	bvs	2f
	bmi	2f
	add.l	d1,d0
	bcs	2f
	bpl	1b
2:	moveq.l	#-1,d0
3:	subq.l	#1,a0
	move.l	(sp)+,d1
	tst.l	d0
	rts

;----------------------------------------------------------------
;文字列表示
print::
	move.l	d0,-(sp)
	move.l	a1,-(sp)
	DOS	_PRINT
	addq.l	#4,sp
	move.l	(sp)+,d0
	rts

;----------------------------------------------------------------
;整数→16進数8桁
hex8::
	movem.l	d1-d2,-(sp)
	moveq.l	#8-1,d2
1:	rol.l	#4,d0
	moveq.l	#$0F,d1
	and.b	d0,d1
	move.b	(2f,pc,d1.w),(a0)+
	dbra	d2,1b
	movem.l	(sp)+,d1-d2
	rts
2:	.dc.b	'0123456789ABCDEF'