playssg.asm
comment *
MASM32 SDK
ml /c /AT /Fl playssg.asm
link16 /t playssg;
*
		.model	tiny
 
FP		struc
FP_OFF		dw	?
FP_SEG		dw	?
FP		ends
 
; Programmable Interrupt Controller / Master
MPIC_OCW1	equ	02h	; Operation Command Word
MPIC_OCW2	equ	00h
MPIC_IMR	equ	02h	; Interrupt Mask Reg.
 
; Programmable Interval Timer
PIT_CNT0	equ	71h	; Counter
PIT_MODE	equ	77h	; Mode Reg.
 
BIOS_FLAG	equ	0501h
 
CLOCK5		equ	24576	; 5MHz系
CLOCK8		equ	19968	; 8MHz系
 
sound		macro	addr, data
		mov	al, addr
		mov	ah, data
		call	wrtpsg
		endm
 
		.code
		.186
		org	0100h
 
;■
main		proc
		mov	ax, 2523h
		mov	dx, offset myint23
		int	21h
 
		sound	08h, 0			; 振幅 A
		sound	07h, 0feh		; ミキサー
 
		call	settimer
@@loop:
		call	play
		jnc	@@loop
 
		call	resettimer
@@exit:
		mov	ax, 4c00h
		int	21h
main		endp
 
;■
play		proc
		mov	ax, count_msec
		cmp	ax, next
		jb	@@exit0
 
		sound	08h, 0			; 振幅 A
 
		mov	si, pos
		cld
		lodsw
		mov	cx, ax
 
		sound	01h, ch			; トーン・ジェネレータ A
		sound	00h, cl
 
		lodsw
		cmp	ax, 0
		je	@@exit1
		mov	cx, ax
 
		sound	08h, 12			; 振幅 A
 
		add	next, cx
		mov	pos, si
@@exit0:
		clc
		ret
@@exit1:
		stc
		ret
play		endp
 
;■
wrtpsg		proc
		mov	dx, 188h		; アドレス
		out	dx, al
		mov	dx, 18ah		; データ
		mov	al, ah
		out	dx, al
		ret
wrtpsg		endp
 
;■
myint23		proc	far
		call	resettimer
		stc
		ret				; retf
myint23		endp
 
;■
settimer	proc
		pushf
		push	es
@@setvector:
		mov	ax, 3508h
		int	21h
		mov	cs:[orgint08].FP.FP_SEG, es
		mov	cs:[orgint08].FP.FP_OFF, bx
 
		mov	dx, offset newint08	; ds
		mov	ax, 2508h
		int	21h
@@setpit:
		mov	bx, CLOCK5
		mov	ax, 0
		mov	es, ax
		test	byte ptr es:[BIOS_FLAG], 80h
		jz	@@skip
		mov	bx, CLOCK8
@@skip:
		cli
		mov	al, 00110110b
		out	PIT_MODE, al
		jmp	$+2
		jmp	$+2
		mov	al, bl
		out	PIT_CNT0, al
		jmp	$+2
		jmp	$+2
		mov	al, bh
		out	PIT_CNT0, al
@@setpic:
		in	al, MPIC_IMR
		and	al, 0feh		; タイマ割り込み許可
		out	MPIC_OCW1, al
 
		pop	es
		popf
		ret
settimer	endp
 
;■
resettimer	proc
		pushf
		cli
		push	ds
		push	ax
		push	dx
@@resetpic:
		in	al, MPIC_IMR
		or	al, 01h			; タイマ割り込み禁止
		out	MPIC_OCW1, al
@@resetvector:
		mov	ax, 2508h
		lds	dx, cs:[orgint08]
		int	21h
 
		pop	dx
		pop	ax
		pop	ds
		popf
		ret
resettimer	endp
 
;■
newint08	proc	far
		push	ax
 
		inc	cs:count_msec
		mov	al, 20h			; 割り込み処理終了(EOI)
		out	MPIC_OCW2, al
 
		pop	ax
		iret
newint08	endp
 
orgint08	dd	0
count_msec	dw	0
 
data		dw	478, 50			; c4
		dw	426, 50			; d4
		dw	379, 50			; e4
		dw	358, 50			; f4
		dw	379, 50			; e4
		dw	426, 50			; d4
		dw	478, 50			; c4
		dw	0, 0			; end
 
pos		dw	offset data
next		dw	0
 
		end	main
 
最終更新:2018年08月21日 21:33