|
|
10 OUT &H40,&H20:::::::OUT &H40,0 20 GOTO 10 |
Main: di ld e,7 ld ix,NoteTable .loop: call Play inc ix inc ix dec e jr nz,.loop jr Main Play: ld b,100 ;おとのながさ(てきとう) .loop: ld l,(ix+0) ;19 ld h,(ix+1) ;19 ld a,$20 ;7 $80=88mk2BEEP out ($40),a ;11 .wait1: dec hl ;6 -+ ld a,l ;4 | or h ;4 | jp nz,.wait1 ;10-+ * n inc hl ;6 ld a,0 ;7 ld l,(ix+0) ;19 ld h,(ix+1) ;19 ld a,0 ;7 out ($40),a ;11 .wait2: dec hl ;6 -+ ld a,l ;4 | or h ;4 | jp nz,.wait2 ;10-+ * n djnz .loop ;13 ret ;=138+(24*n*2) NoteTable: dw ((3993600 / 261) - 138) / 48 ;o4c dw ((3993600 / 293) - 138) / 48 ;o4d dw ((3993600 / 329) - 138) / 48 ;o4e dw ((3993600 / 349) - 138) / 48 ;o4f dw ((3993600 / 391) - 138) / 48 ;o4g dw ((3993600 / 440) - 138) / 48 ;o4a dw ((3993600 / 493) - 138) / 48 ;o4b |
N88-BASIC での割り込みテーブル | ||||
---|---|---|---|---|
Lv.0 | $F300-$F301 | RXRDY | RS-232C 受信割り込み | ↑ 高 低 ↓ |
Lv.1 | $F302-$F303 | VRTC | 画面終了割り込み 1/60 秒 | |
Lv.2 | $F304-$F305 | CLOCK | リアルタイムクロック 1/600 秒 | |
Lv.3 | $F306-$F307 | INT4 | ユーザー割り込み (音源) | |
Lv.4 | $F308-$F309 | INT3 | ユーザー割り込み (音源) | |
Lv.5 | $F30A-$F30B | INT2 | ユーザー割り込み | |
Lv.6 | $F30C-$F30D | FDINT1 | FDD 用リザーブ | |
Lv.7 | $F30E-$F30F | FDINT0 | FDD 用リザーブ |
I/O ポート $E4 【入力・出力】 | ||
---|---|---|
bit | 3 | 0=割り込みレベルを参照して割り込みを発生させる 1=優先順位による割り込み |
bit | 2-0 | 割り込みレベル 0-7 |
I/O ポート $E6 【出力】 | ||
---|---|---|
bit | 2 | USART 割り込みマスク 0=禁止 1=許可 |
bit | 1 | VRTC 割り込みマスク 0=禁止 1=許可 |
bit | 0 | リアルタイムクロック割り込みマスク 0=禁止 1=許可 |
I/O ポート $32 【入力・出力】 | ||
---|---|---|
bit | 7 | 音源割り込みマスク 0=割り込み許可 1=割り込み不可 |
bit | 6 | グラフィックVRAMアクセスモード 0=独立アクセスモード 1=ALUアクセスモード |
bit | 5 | カラーモード 0=デジタルモード 1=アナログモード |
bit | 4 | 高速RAM/メインRAMバンク選択 0=高速テキストRAM選択 1=メインRAM選択 |
bit | 3 | 画面出力モード 00=テレビ/ビデオモード 01=なし 10=アナログRGBモード 11=オプションモード |
bit | 2 | |
bit | 1 | 内部EROM選択 00=内部EROMバンク0選択 01=内部EROMバンク1選択 02=内部EROMバンク2選択 03=内部EROMバンク3選択 |
bit | 0 |
I/O ポート $AA 【出力】 | ||
---|---|---|
bit | 7 | 音源割り込みマスク 0=割り込み許可 1=割り込み不可 |
bit | 6-0 |
・FM 音源タイマー B が満期
->FM 音源レジスタ $27 のタイマー B オーバーフロー受け付けフラグが ON
->FM 音源 OPNA レジスタ $29 のタイマー B 使用可能フラグが有効
->FM 音源 OPNA レジスタ $10 のタイマー B マスクフラグが降りている
-> I/O ポート $32 の音源割り込みマスク「許可」
-> I/O ポート $E4 の割り込みレベルの条件を満たしている
-> Z80 の状態が割り込み許可 (EI)
-> 割り込み発生!
・1/600秒カウンタ満期
-> I/O ポート$E6 の割り込みマスク「許可」
-> I/O ポート $E4 の割り込みレベルの条件を満たしている
-> Z80 の状態が割り込み許可 (EI)
-> 割り込み発生!
|
Sount_Interrupt: di push af ;FM 音源割り込みでここに来たので FM 音源ドライバの処理を行う push bc push de push hl push ix ld d,$27 ;FM 音源コントロールポート ld e,%00101010 ;FM 音源タイマー B を再セット call WriteOPN ld a,7 ;割り込みレベル再設定 out ($E4),a call Sound_Driver ;音源ドライバ処理 pop ix pop hl pop de pop bc pop af ei ret |
IntSound: in a,($44) rrca jr c,.timera rrca jr nc,.exit .timerb: ld d,$27 ;mode. timer-ctrl ld e,%00101111 ;[ResetB] call WriteOPN ここに Timer-B の処理を書く jr IntSound ;必ず両方のフラグの処理を消化する .timera: ld d,$27 ;mode. timer-ctrl ld e,%00011111 ;[ResetA] call WriteOPN ここに Timer-A の処理を書く jr IntSound ;必ず両方のフラグの処理を消化する .exit: ld a,5 out ($E4),a ei ret |
Check_N88ROM: ld a,%00111001 ;N88-BASIC, ROM&RAM out ($31),a ld a,($79D7) cp $32 jr c,.PC8801 ;1.0-1.1 初代 jr z,.PC8801A ;1.2 A cp $33 jr z,.PC8801mk2 ;1.3 mk2 cp $34 jr z,.PC8801mk2SRTR ;1.4 SR/TR cp $38 jr c,.PC8801FRMR ;1.5-1.7 FR/MR jr z,.PC8801FHMH ;1.8 FH/MH ld a,($79D8) cp $0D jr z,.PC8801FAMAVAx ;1.9 VA/FA/MA/VA2/VA3 cp $31 jr z,.PC8801FEMA2 ;1.91 FE/MA2 cp $32 jr z,.PC98DO ;1.92 DO cp $33 jr z,.PC8801FE2MC ;1.93 FE2/MC cp $34 jr z,.PC98DOP ;1.94 DO+ jr .PC8801unknown ;不明 以下個別の処理(略) |
Check_Mode: in a,($31) ;bit76:10=V1S 11=V1H 01=V2 rlca ld hl," 2" jr nc,.mode rlca ld hl,"H1" jr c,.mode ld hl,"S1" .mode: in a,($6E) ;bit7:0=8MHz 1=4MHz (FH以降) rlca ld a,"4" jr c,.spd ld a,"8" .spd: ld (SPEED),a ld (MODE+1),hl ret SPEED: db "4MHz",0 MODE: db "V2S Mode",0 |
Check_MC: in a,($40) and %00000010 ld hl,$01C0 ;15KHz jr nz,.skip1 ld hl,$0100 ;24KHz .skip1: ld bc,0 call WaitVblank .loop: ld ix,($0000) inc bc in a,($40) and $20 jr nz,.loop ;vblank の間ループを続ける sbc hl,bc ; bc>hl なら 8MHz-H モードと見なす ld hl,"H-" jr c,.skip2 ld hl,"S-" .skip2: ret WaitVblank: in a,($40) and $20 jr nz,WaitVblank ;bit5 一旦ディスプレイサイクルになるまで待つ .wait: in a,($40) and $20 ;bit5 ディスプレイサイクル → Vblank になったら ret jr z,.wait ret |
Check_ExtRAM: ld a,%00111011 out ($31),a ;64KRAM 選択 ld a,%00010001 out ($E2),a ld b,0 ld hl,$AA00 .loop1: ld a,b out ($E3),a ld ($0000),hl ;適当に埋める dec l djnz .loop1 ;降順 xor a out ($E2),a ld hl,$8801 ld ($0000),hl ;メインRAMに書き込み ld a,%00010001 out ($E2),a ld bc,0 .loop2: ld a,b out ($E3),a ld hl,($0000) ld a,h cp $88 jr z,.skip cp $AA jr nz,.skip ld a,l cp b jr nz,.skip inc c .skip: inc b jp nz,.loop2 ;昇順 xor a out ($E2),a out ($E3),a ld a,c ;バンク数で返る。32K*バンク数byteのメモリがあるはず。 ld (Machine_ExtRAM),a ret |
例 | 内蔵 | 拡張 | INT3 | INT4 | 割込制御 | FM1 | FM2 | FM3 | FM4 | JOYSTICK |
---|---|---|---|---|---|---|---|---|---|---|
PC-8001mk2 +PC-8801-11 | なし | OPN | 80側 | 88側 | $AA | $A8,$A9 | ? | |||
PC-8001mk2 +PC-8801-23 | なし | OPNA | 拡張 | $AA | $A8,$A9 | $AC,$AD | ? | |||
PC-8001mk2SR | OPN | 内蔵 | $33.bit1 | $44,$45 | ? | |||||
PC-8001mk2SR +PC-8801-11 | OPN | OPN | 内蔵 | 88側 | $33,$AA | $44,$45 | $A8,$A9 | ? | ||
PC-8001mk2SR +PC-8801-23 | OPN | OPNA | 内蔵 | 拡張 | $33,$AA | $44,$45 | $A8,$A9 | $AC,$AD | ? | |
PC-8801 +PC-8801-11 | なし | OPN | 88側 | 80側 | $AA | $A8,$A9 | ? | |||
PC-8801 +PC-8801-23 | なし | OPNA | 拡張 | $AA | $A8,$A9 | $AC,$AD | ? | |||
PC-8801mk2SR | OPN | 内蔵 | $32 | $44,$45 | 内蔵 | |||||
PC-8801mk2SR +PC-8801-11 | OPN | OPN | 内蔵 | 80側 | $32,$AA | $44,$45 | $A8,$A9 | ? | ||
PC-8801mk2SR +PC-8801-23 | OPN | OPNA | 両方 | $32,$AA | $44,$45 | $A8,$A9 | $AC,$AD | ? | ||
PC-8801FA | OPNA | 内蔵 | $32 | $44,$45 | $46,$47 | 内蔵 | ||||
PC-8801FA +PC-8801-11 | OPNA | OPN | 内蔵 | 80側 | $32,$AA | $44,$45 | $46,$47 | $A8, $A9 | ? | |
PC-8801FA +PC-8801-23 | OPNA | OPNA | 両方 | $32,$AA | $44,$45 | $46,$47 | $A8,$A9 | $AC,$AD | ? | |
PC-8801xH +PC-8801-24 | OPN | OPNA | 拡張 | $32 | × | $44,$45 | $46,$47 | ? | ||
PC-8801FE +PC-8801-25 | OPN | OPNA | 拡張 | $32 | × | $44,$45 | $46,$47 | 内蔵 | ||
PC-8801xH +Re:BitrhFM | OPN | OPNA | 拡張 | $32 | × | $44,$45 | $46,$47 | ? |
10 new cmd 20 cmd play"@13v15c" |
10 'fm(opn) sound test 20 DEFINT A-Z:CH=0:OCT=3:FRQ=&H26A 'o4c 30 READ AL,FB 40 REG=&HB0+CH:DAT=FB*8+AL:GOSUB 460 50 OP=0:GOSUB 360:OP=2:GOSUB 360:OP=1:GOSUB 360:OP=3:GOSUB 360 60 ' 70 REG=&HA4+CH:DAT=((OCT*2048+FRQ) AND &HFF00)/256:GOSUB 460 80 REG=&HA0+CH:DAT=((OCT*2048+FRQ) AND &HFF):GOSUB 460 90 REG=&H28:DAT=&HF0+CH:GOSUB 460 100 PRINT"PUSH SPACE TO KEYOFF" 110 IF INP(9)<>191 THEN 110 120 REG=&H28:DAT=CH:GOSUB 460 130 END 360 'write fm parameter to (op) 370 READ AR,DR,SR,RR,SL,TL,KS,ML,DT,SSG 380 REG=&H30+CH+OP*4:DAT=DT*16+ML:GOSUB 460 390 REG=&H40+CH+OP*4:DAT=TL:GOSUB 460 400 REG=&H50+CH+OP*4:DAT=KS*64+AR:GOSUB 460 410 REG=&H60+CH+OP*4:DAT=DR:GOSUB 460 420 REG=&H70+CH+OP*4:DAT=SR:GOSUB 460 430 REG=&H80+CH+OP*4:DAT=SL*16+RR:GOSUB 460 440 REG=&H90+CH+OP*4:DAT=SSG:GOSUB 460 450 RETURN 460 'write fm register 470 OUT &H44,REG 480 OUT &H45,DAT 490 RETURN 500 ' AL FB 510 DATA 2, 7 520 ' AR DR SR RR SL TL KS ML DT SSG-EG 530 DATA 31,12, 4,10, 1,32, 0,12, 0, 0 540 DATA 31, 2, 4, 6,15,57, 3,15, 1, 0 550 DATA 31,12, 4, 6, 0,30, 0, 1, 0, 0 560 DATA 31, 5, 7, 7, 2, 0, 2, 3, 5, 0 |
I/O ポート $44 【入力】 | ||
---|---|---|
bit | 7 | 1=データをレジスタにセット中 |
bit | 1 | 1=OPN タイマー B がオーバーフローした |
bit | 0 | 1=OPN タイマー A がオーバーフローした |
I/O ポート $44 【出力】 | ||
---|---|---|
bit | 7-6 | OPN レジスタ指定 |
I/O ポート $45 【入出力】 | ||
---|---|---|
bit | 7-6 | OPN データ入出力 |
WriteOPN: in a,($44) rlca jr c,WriteOPN ld a,d out ($44),a ld a,(ix+0) ;dummy ld a,e out ($45),a ret |
OPN レジスタ $27 【出力】 | ||
---|---|---|
bit | 7-6 | 00=通常モード 01=効果音モード 10=音声合成モード |
bit | 5 | 1=フラグB リセット |
bit | 4 | 1=フラグA リセット |
bit | 3 | 1=タイマーB のオーバーフロー時にフラグB を 1 にする。0=オーバーフローを無視 |
bit | 2 | 1=タイマーA のオーバーフロー時にフラグA を 1 にする。0=オーバーフローを無視 |
bit | 1 | 1=タイマーB 始動 0=停止 |
bit | 0 | 1=タイマーA 始動 0=停止 |
OPN レジスタ $2F 【出力】 | ||
---|---|---|
bit | 7-0 | FM 音源の分周比 1/2 SSG 音源の分周比 1/1 OPN への最大入力クロック 1.4MHz |
OPN レジスタ $2D 【出力】 | ||
---|---|---|
bit | 7-0 | FM 音源の分周比 1/6 SSG 音源の分周比 1/4 OPN への最大入力クロック 4.2MHz |
OPN レジスタ $2D,$2E 【出力】 | ||
---|---|---|
bit | 7-0 | FM 音源の分周比 1/3 SSG 音源の分周比 1/2 OPN への最大入力クロック 2.1MHz |
PadInit: ;初回に一度呼ぶ ld a,7 out ($44),a in a,($45) and %00111111 ;PSG I/O Port A/B 共に入力にする out ($45),a ret PadRead: ld a,$0E out ($44),a in a,($45) cpl ;....RLDU and $0F ;押したところが 1 になる ld (Pad),a ld a,$0F out ($44),a in a,($45) cpl and %00000011 ;ボタン0=bit0 ボタン1=bit1 ld (Button),a ret |
80mk2/88mk2 の汎用 I/O ポート【入出力】 | 88SR の汎用 I/O ポート【入出力】 | ||||
---|---|---|---|---|---|
pin1 | UIP2 | IN $30.bit7 | JIP1 | IN OPN($0E).bit0 | |
pin2 | UIP1 | IN $30.bit6 | JIP2 | IN OPN($0E).bit1 | |
pin3 | UOP1 | OUT $30.bit6 | JIP3 | IN OPN($0E).bit2 | |
pin4 | UOP2 | OUT $30.bit7 | JIP4 | IN OPN($0E).bit3 | |
pin5 | GND | - | +5V | - | |
pin6 | UOP3 | OUT $10.bit7 | JIOP1 | IN/OUT OPN($0F).bit0 | |
pin7 | GND | - | JIOP2 | IN/OUT OPN($0F).bit1 | |
pin8 | UINT2 | 負論理 | JOP1 | OUT $40.bit6 | |
pin9 | +5V | - | GND | - |
ld c,$44 call .sub ret nc ;c=$44 側に OPNA がある ld c,$A8 call .sub ret nc ;c=$A8 側に OPNA がある jp notexist ;OPNA が存在しない .sub: ld a,$FF out (c),a inc c in a,(c) dec c cp 1 ret z ;存在したら cf=0 scf ret ;存在しなければ cf=1 |
I/O ポート $46 【入力】 | ||
---|---|---|
bit | 7 | [BUSY]1=データをレジスタにセット中 |
bit | 6 | 未使用 |
bit | 5 | [PCMBSY] 1=ADPCM録音・再生中 |
bit | 4 | [ZERO] 1=ADPCM録音中に無音状態になった |
bit | 3 | [BRDY] 1=ADPCM録音・再生またはメモリへの格納が 1byte 完了した |
bit | 2 | [EOS] 1=ADPCM録音・再生が終端アドレスに達した、またはPCM再生周期になった |
bit | 1 | [FLAGB]1=OPNA タイマー B がオーバーフローした |
bit | 0 | [FLAGA]1=OPNA タイマー A がオーバーフローした |
I/O ポート $46 【出力】 | ||
---|---|---|
bit | 7-6 | OPNA レジスタ指定 |
I/O ポート $47 【入出力】 | ||
---|---|---|
bit | 7-6 | OPNA データ入出力 |
OPNA レジスタ $29 【出力】 | ||
---|---|---|
bit | 7 | 1=FM4-6, ADPCM を使用可能にする |
bit | 4 | 1=ADPCM録音中に無音状態になった時に[ZERO]フラグを立て割り込みをかける |
bit | 3 | 1=ADPCM録音・再生またはメモリへの格納が 1byte 完了したときに[BRDY]フラグを立て割り込みをかける |
bit | 2 | 1=ADPCM録音・再生が終端アドレスに達した、またはPCM再生周期になった時に[EOS]フラグを立て割り込みをかける |
bit | 1 | 1=OPNA タイマー B がオーバーフローしたときに[FLAGB]を立て割り込みをかける |
bit | 0 | 1=OPNA タイマー A がオーバーフローしたときに[FLAGA]を立て割り込みをかける |
OPNA レジスタ $10 【出力】 | ||
---|---|---|
bit | 7 | 1=全フラグを 0 にする。bit4-0 の設定は無視 |
bit | 4 | 1=[ZERO]を常に 0 にマスクする |
bit | 3 | 1=[BRDY]を常に 0 にマスクする |
bit | 2 | 1=[EOS]を常に 0 にマスクする |
bit | 1 | 1=[FLAGB]を常に 0 にマスクする |
bit | 0 | 1=[FLAGA]を常に 0 にマスクする |
WriteOPNA: in a,($44) rlca jr c,WriteOPNA ld a,d out ($44),a nop ;dummy ld a,e out ($45),a ret |
ADPCM_Init: ;初回に一度だけ呼び出せばよい ld c,$46 ld de,$1000 ;フラグコントロール どのフラグもマスクしない call WriteFM2 ld de,$1080 ;フラグコントロール 全てのステータスフラグを0に call WriteFM2 ld de,$0102 ;x8 DRAM call WriteFM2 ld de,$04FF ;ストップアドレス下位 $04 call WriteFM2 ld de,$051F ;ストップアドレス上位 $05 call WriteFM2 ld de,$0CFF ;リミットアドレス下位 $FF call WriteFM2 ld de,$0D1F ;リミットアドレス上位 $1F jp WriteFM2 ADPCM_READ2: ld c,$46 ld de,$0020 ;$00 メモリアクセス許可 call WriteFM2 ld hl,(ADPCM_START) ld d,$02 ld e,l ;$02 スタートアドレス下位 call WriteFM2 ld d,$03 ld e,h ;$03 スタートアドレス上位 call WriteFM2 ex de,hl ld hl,(ADPCM_END) or a sbc hl,de ;Length=End-Start+1 inc l ;+1はdec hlと相殺 inc h ex de,hl ld a,$08 out (c),a inc c in a,(c) in a,(c) ;2回分空読みする ld hl,(ADPCM_ADR) ;書き込み先 .loop: ld b,32 inir ;BRDY を見る必要なし. フラグのリセットも必要なし. dec e jp nz,.loop dec d jp nz,.loop dec c ld de,$0001 ;$00 コントロール1 リセット jp WriteFM2 |
I/O ポート $88 【出力】 | ||
---|---|---|
bit | 7-6 | OPM レジスタ指定 |
I/O ポート $89 【出力】 | ||
---|---|---|
bit | 7-6 | OPM データ出力 |
I/O ポート $89 【入力】 | ||
---|---|---|
bit | 7 | 1=データをレジスタにセット中 |
bit | 1 | 1=OPM タイマー B がオーバーフローした |
bit | 0 | 1=OPM タイマー A がオーバーフローした |
10 'fm(opm) sound test 20 DEFINT A-Z:CH=0:OCT=3:LR=3:KC=0:KF=0 'o4c 30 READ AL,FB,WF,SY,SPD,PMD,AMD,PMS,AMS 40 REG=&H18:DAT=SPD:GOSUB 460 50 REG=&H19:DAT=&H80+PMD:GOSUB 460 60 REG=&H19:DAT=AMD:GOSUB 460 70 REG=&H1B:DAT=WF:GOSUB 460 80 REG=&H20+CH:DAT=LR*64+FB*8+AL:GOSUB 460 90 REG=&H38+CH:DAT=PMS*16+AMS:GOSUB 460 100 OP=0:GOSUB 370:OP=2:GOSUB 370:OP=1:GOSUB 370:OP=3:GOSUB 370 110 ' 120 REG=&H28+CH:DAT=OCT*16+KC:GOSUB 460 130 REG=&H30+CH:DAT=KF*4:GOSUB 460 140 REG=&H8:DAT=&H78+CH:GOSUB 460 150 PRINT"PUSH SPACE TO KEYOFF" 160 IF INP(9)<>191 THEN 160 170 REG=&H8:DAT=CH:GOSUB 460 180 END 370 'write fm parameter to (op) 380 READ AR,DR,SR,RR,SL,TL,KS,ML,DT1,DT2,AME 390 REG=&H40+CH+OP*8:DAT=DT1*16+ML:GOSUB 460 400 REG=&H60+CH+OP*8:DAT=TL:GOSUB 460 410 REG=&H80+CH+OP*8:DAT=KS*64+AR:GOSUB 460 420 REG=&HA0+CH+OP*8:DAT=AME*128+DR:GOSUB 460 430 REG=&HC0+CH+OP*8:DAT=DT2*64+SR:GOSUB 460 440 REG=&HE0+CH+OP*8:DAT=SL*16+RR:GOSUB 460 450 RETURN 460 'write fm register 470 OUT &H88,REG 480 OUT &H89,DAT 490 RETURN 500 ' AL FB WF SY SPD PMD AMD PMS AMS 510 DATA 2, 7, 2, 1,220, 0, 4, 1, 1 520 ' AR DR SR RR SL TL KS ML DT1 DT2 AME 530 DATA 31, 5, 7, 4, 9,37, 1, 1, 5, 0, 0 540 DATA 22, 0, 4, 5, 4,62, 1, 5, 2, 0, 0 550 DATA 29, 0, 4, 5, 4,77, 1, 1, 7, 0, 0 560 DATA 31, 7, 6, 5, 4, 0, 2, 1, 1, 0, 1 |
WriteOPM: in a,($89) rlca jr c,WriteOPM ld a,d out ($88),a ld a,(ix+0) ;dummy ld a,e out ($89),a ret |
|
|
||||||||||||
|
|
|
|
||||||||||||
|
|
I/O ポート $C2 【入出力】 | ||
---|---|---|
bit | 7-6 | MIDI 通信用 8251 データ入出力 |
I/O ポート $C3 【入出力】 | ||
---|---|---|
bit | 7-6 | MIDI コントロール用 8251 コマンド出力・ステータス入力 |
10 'PC-8801-10 and GSX-8800 PSG Sound Test 20 CLK=3993600 30 CS=0:R=7:D=&H38:GOSUB 200:CS=1:R=7:D=&H38:GOSUB 200 40 CS=2:R=7:D=&H38:GOSUB 200:CS=3:R=7:D=&H38:GOSUB 200 50 CS=0:R=8:D=15:GOSUB 200:CS=1:R=8:D=15:GOSUB 200 60 CS=2:R=8:D=15:GOSUB 200:CS=3:R=8:D=15:GOSUB 200 100 CS=0:D=CLK/32/261:GOSUB 230 'o4c 110 CS=1:D=CLK/32/329:GOSUB 230 'o4e 120 CS=2:D=CLK/32/392:GOSUB 230 'o4g 130 CS=3:D=CLK/32/523:GOSUB 230 'o5c 140 PRINT"PUSH SPACE TO STOP" 150 IF INP(9)<>191 THEN 150 160 CS=0:R=8:D=0:GOSUB 200:CS=1:GOSUB 200 170 CS=2:GOSUB 200:CS=3:GOSUB 200 180 END 190 'write PSG 200 OUT &HA0+CS*2,R 210 OUT &HA1+CS*2,D 220 RETURN 230 'write frq 240 OUT &HA0+CS*2,0 250 OUT &HA1+CS*2,(D AND 255) 260 OUT &HA0+CS*2,1 270 OUT &HA1+CS*2,(D AND &HFF00) / 256 280 RETURN |
I/O ポート $02 【PIT コントロール出力】 | ||
---|---|---|
bit | 7 | チャンネル 2 出力 1=ON 0=OFF |
bit | 6 | チャンネル 1 出力 1=ON 0=OFF |
bit | 5 | PCG ROM コピー |
bit | 4 | PCG RAM ライト |
bit | 3 | チャンネル 0 出力 1=ON 0=OFF |
bit | 2 | RAM A10 |
bit | 1 | RAM A9 |
bit | 0 | RAM A8 |
I/O ポート $0F 【PIT コントロール出力】 | ||
---|---|---|
bit | 7-6 | カウンタチャンネル指定 00=チャンネル 0 01=チャンネル 1 10=チャンネル 2 |
bit | 5-4 | カウンタアクセスモード 11=16bit ロード(下位・上位の順) 10=上位 8bit のロード 01=下位 8bit のロード 00=カウント値ラッチ |
bit | 3-1 | カウントモード 000=mode0:ターミナルカウント 001=mode1:プログラマブルワンショット 010=110=mode2:レートジェネレータ 011=111=mode3:方形波レートジェネレータ 100=mode4:ソフトウェアトリガストローブ 101=mode5:ハードウェアトリガストローブ |
bit | 0 | PIT カウントモード 1=BCD 0=2進数 |
I/O ポート $0C 【PIT チャンネル 0 出力】 | ||
---|---|---|
bit | 7-0 | チャンネル 0 カウント値 |
I/O ポート $0D 【PIT チャンネル 1 出力】 | ||
---|---|---|
bit | 7-0 | チャンネル 1 カウント値 |
I/O ポート $0E 【PIT チャンネル 2 出力】 | ||
---|---|---|
bit | 7-0 | チャンネル 2 カウント値 |
10 'PCG-8800 sound output test 20 OUT &H2,&HC8 'pcg sound on 30 CH=0:F=15301:GOSUB 100 '3993600 / 261Hz o4c 40 CH=1:F=12138:GOSUB 100 '3993600 / 329Hz o4e 50 CH=2:F=10187:GOSUB 100 '3993600 / 392Hz o4g 60 PRINT "hit space to stop" 70 IF INP(9)<>191 THEN 70 80 OUT &H2,0 'pcg sound off 90 END 100 ' 110 FL=F AND &HFF 120 FH=(F AND &HFF00) / 256 200 ' 210 OUT &HF,&H36+CH*64 220 OUT &HC+CH,FL 230 OUT &HC+CH,FH 240 RETURN |
ld a,$C8 out ($02),a ;PCG sound ch.0-2 on ld a,%00110000 ;ch.0/16bit load/mode0/binary out ($0F),a ld hl,PCMDATA ;7800Hz 8bit PCM ld de,PCMEND - PCMDATA .loop: ld a,(hl) ;7 inc hl ;6 add a,a ;4 out ($0C),a ;11 ld a,0 ;7 rla ;4 out ($0C),a ;11 ld b,33 ;7 ld b,33 ;7 djnz $ ;424 (13*32+8) dec de ;6 ld a,d ;4 or e ;4 jp nz,.loop ;10 =512clk xor a out ($02),a |
I/O ポート $AC 【出力】 | ||
---|---|---|
bit | 7-6 | DCSG1 データ出力 |
I/O ポート $AD,$AE 【出力】 | ||
---|---|---|
bit | 7-6 | クロックマスク / 解除 |
I/O ポート $AF 【出力】 | ||
---|---|---|
bit | 7-6 | DCSG2 データ出力 |
10 ' ADDCOM Sound Unit SN76489 TEST 15 OUT &HAE,0 20 PT=&HAC:F=478:GOSUB 80 '3993600 / 32 / 261 o4c 30 PT=&HAF:F=318:GOSUB 80 '3993600 / 32 / 392 o4g 40 IF INP(9)<>191 THEN 40 50 PT=&HAC:D=&H80+CH*32+16+15:GOSUB 120 60 PT=&HAF:D=&H80+CH*32+16+15:GOSUB 120 70 END 80 CH=0:V=0:D=&H80+CH*32+16+V:GOSUB 120 90 CH=0:D=&H80+CH*32+(F AND 15):GOSUB 120 100 CH=0:D=(F AND &H3F0)/16:GOSUB 120 110 RETURN 120 DT=(D AND 1)*128 'invert bit7<->bit0 130 DT=DT+(D AND 2)*32 140 DT=DT+(D AND 4)*8 150 DT=DT+(D AND 8)*2 160 DT=DT+(D AND 16)/2 170 DT=DT+(D AND 32)/8 180 DT=DT+(D AND 64)/32 190 DT=DT+(D AND 128)/128 200 OUT PT,DT 210 RETURN |
I/O ポート $90 【PPI ポート A 出力】 | ||
---|---|---|
bit | 7-0 | PSG レジスタ・データ |
I/O ポート $92 【PPI ポート C 入出力】 | ||
---|---|---|
bit | 5-4 | レジスタ指定=11 データ書き込み=10 |
bit | 7-0 | 全ビット 0 を書き込むと書き込み確定 |
bit | 0 | 0,1 が定期的に読み出せる。 |
I/O ポート $93 【PPI コントロール出力】 | ||
---|---|---|
bit | 7 | 1 |
bit | 6-5 | PortA, PortC上位4bitのモード選択 00=mode0 01=mode1 10=11=mode2 |
bit | 4 | PortA 0=出力 1=入力 |
bit | 3 | PortC上位4bit 0=出力 1=入力 |
bit | 2 | PortB, PortC下位4bitのモード選択 0=mode0 1=mode1 |
bit | 1 | PortB 0=出力 1=入力 |
bit | 0 | PortC下位4bit 0=出力 1=入力 |
10 'PCS-8081 20 CLK=3579545 30 OUT &H93,&H81:OUT &H97,&H81:OUT &H9B,&H81:OUT &H9F,&H81 40 FRQ=CLK/261 'o4c 100 CS=0:REG=7:DAT=&H38:GOSUB 500 110 CS=0:REG=0:DAT=FRQ AND 255:GOSUB 500 120 CS=0:REG=1:DAT=(FRQ AND &HFF00)/256:GOSUB 500 130 CS=0:REG=8:DAT=15:GOSUB 500 180 PRINT"PUSH SPACE TO STOP" 190 IF INP(9)<>&HBF THEN 190 200 REG=8:DAT=0:CS=0:GOSUB 500:CS=1:GOSUB 500 210 REG=8:DAT=0:CS=2:GOSUB 500:CS=3:GOSUB 500 400 END 500 'write PSG ChipSelect=0/1/2/3 510 OUT &H92+CS*4,&H30 520 OUT &H90+CS*4,REG 530 OUT &H92+CS*4,0 540 OUT &H92+CS*4,&H20 550 OUT &H90+CS*4,DAT 560 OUT &H92+CS*4,0 570 RETURN |
I/O ポート $90 【PPI ポート A 出力】 | ||
---|---|---|
bit | 7-0 | PSG1 レジスタ・データ |
I/O ポート $91 【PPI ポート B 出力】 | ||
---|---|---|
bit | 7-0 | PSG2 レジスタ・データ |
I/O ポート $92 【PPI ポート C 入出力】 | ||
---|---|---|
bit | 7-6 | PSG2: レジスタ指定=11 データ書き込み=10 |
bit | 5-4 | PSG1: レジスタ指定=11 データ書き込み=10 |
bit | 7-0 | 全ビット 0 を書き込むと書き込み確定 |
bit | 0 | 0,1 が定期的に読み出せる。 |
I/O ポート $93 【PPI コントロール出力】 | ||
---|---|---|
bit | 7 | 1 |
bit | 6-5 | PortA, PortC上位4bitのモード選択 00=mode0 01=mode1 10=11=mode2 |
bit | 4 | PortA 0=出力 1=入力 |
bit | 3 | PortC上位4bit 0=出力 1=入力 |
bit | 2 | PortB, PortC下位4bitのモード選択 0=mode0 1=mode1 |
bit | 1 | PortB 0=出力 1=入力 |
bit | 0 | PortC下位4bit 0=出力 1=入力 |
10 'PCS-8007 20 CLK=3579545 30 OUT &H93,&H81:OUT &H97,&H81 40 FRQ=CLK/261 'o4c 100 CS=0:REG=7:DAT=&H38:GOSUB 500 110 CS=0:REG=0:DAT=FRQ AND 255:GOSUB 500 120 CS=0:REG=1:DAT=(FRQ AND &HFF00)/256:GOSUB 500 130 CS=0:REG=8:DAT=15:GOSUB 500 180 PRINT"PUSH SPACE TO STOP" 190 IF INP(9)<>&HBF THEN 190 200 CS=0:REG=8:DAT=0:GOSUB 500:CS=1:GOSUB 500 210 CS=2:REG=8:DAT=0:GOSUB 500:CS=3:GOSUB 500 400 END 500 'write PSG ChipSelect=0/1/2/3 510 OUT &H92+(CS AND 2)*2,&H30*4^(CS AND 1) 520 OUT &H90+(CS AND 2)*2+(CS AND 1),REG 530 OUT &H92+(CS AND 2)*2,0 540 OUT &H92+(CS AND 2)*2,&H20*4^(CS AND 1) 550 OUT &H90+(CS AND 2)*2+(CS AND 1),DAT 560 OUT &H92+(CS AND 2)*2,0 570 RETURN |
I/O ポート $82 【出力】 | ||
---|---|---|
bit | 7-0 | PSG レジスタ指定 |
I/O ポート $83 【出力】 | ||
---|---|---|
bit | 7-6 | PSG データ書き込み |
10 'PSG+CTC (I/O:1981.12) 20 CLK=3993600 30 FRQ=CLK/261 'o4c 100 CS=0:REG=7:DAT=&H38:GOSUB 500 110 CS=0:REG=0:DAT=FRQ AND 255:GOSUB 500 120 CS=0:REG=1:DAT=(FRQ AND &HFF00)/256:GOSUB 500 130 CS=0:REG=8:DAT=15:GOSUB 500 140 PRINT"PUSH SPACE TO STOP" 150 IF INP(9)<>&HBF THEN 190 160 CS=0:REG=8:DAT=0:GOSUB 500 400 END 500 'write PSG 510 OUT &H82,REG 520 OUT &H83,DAT 530 RETURN |
I/O ポート $84 【CTC ch.0 出力】 | ||
---|---|---|
bit | 7 | 割り込みイネーブル 1:許可 0:禁止 |
bit | 6 | モードの設定。 1:カウンタモード 0:タイマーモード |
bit | 5 | プリスケールの選択。タイマモードにおいてのみ意味がある。 1:1/256 0:1/16 供給クロック 4MHz に対する分周比を指定する。 |
bit | 4 | エッジの選択。無視して良い。 タイマモードの時は bit3 で使うトリガの方向(立ち上がり=1, 立ち下がり=0 を決める) カウンタモードの時は数えるパルスの方向を決める(立ち上がり=1, 立ち下がり=0) |
bit | 3 | トリガの有無。タイマモードにおいてのみ意味がある。無視して良い。 |
bit | 2 | タイムコンスタントの設定。bit2=1 で、次の 1byte がタイムコンスタントであることを示す。 |
bit | 1 | リセット。bit1=1 で停止。もし bit2=1 ならタイムコンスタントが書き込まれた後、動作開始。 |
bit | 0 | 常に 1 にする。ch.0 の場合は bit0=0 ならば割り込みベクタ設定 |
I/O ポート $85 【CTC ch.1 出力】 | ||
---|---|---|
bit | 7-0 | ch.0 と同じ |
I/O ポート $86 【CTC ch.2 出力】 | ||
---|---|---|
bit | 7-0 | ch.0 と同じ |
I/O ポート $87 【CTC ch.3 出力】 | ||
---|---|---|
bit | 7-0 | ch.0 と同じ |
Table: jr Main dw Dummy dw Dummy dw IntCTC dw Dummy dw Dummy dw Dummy dw Dummy Dummy: ei ret Main: di im 2 ld a,Table >> 8 ld i,a ld a,$FF out ($E4),a ld a,CTC_SETVECTOR + $00 out ($84),a ld a,CTC_DISABLE | CTC_TIMER | CTC_PRESCALE256 | CTC_EDGE_UP | CTC_CONSTANT | CTC_RESET | CTC_SETCMD out ($86),a ld a,$41 ;3993600/256/65=240(Hz) out ($86),a ld a,CTC_ENABLE | CTC_COUNTER | CTC_PRESCALE16 | CTC_EDGE_UP | CTC_CONSTANT | CTC_RESET | CTC_SETCMD out ($87),a ld a,$F0 ;240Hz/240=1Hz out ($87),a ei jr $ IntCTC: push af ld a,$FF out ($E4),a 〜長いので略〜 pop af ei ret |
I/O ポート $87 【PPI コントロール出力】 | ||
---|---|---|
bit | 7 | 1 |
bit | 6-5 | PortA, PortC上位4bitのモード選択 00=mode0 01=mode1 10=11=mode2 |
bit | 4 | PortA 0=出力 1=入力 |
bit | 3 | PortC上位4bit 0=出力 1=入力 |
bit | 2 | PortB, PortC下位4bitのモード選択 0=mode0 1=mode1 |
bit | 1 | PortB 0=出力 1=入力 |
bit | 0 | PortC下位4bit 0=出力 1=入力 |
I/O ポート $84 【PPI ポート A 出力】 | ||
---|---|---|
bit | 7-0 | PSG レジスタ・データ |
I/O ポート $85 【PPI ポート B 出力】 | ||
---|---|---|
bit | 7-6 | PSG4: レジスタ指定=11 データ書き込み=10 解除=00 |
bit | 5-4 | PSG3: レジスタ指定=11 データ書き込み=10 解除=00 |
bit | 3-2 | PSG2: レジスタ指定=11 データ書き込み=10 解除=00 |
bit | 1-0 | PSG1: レジスタ指定=11 データ書き込み=10 解除=00 |
10 '12ch Synth Unit (Oh!PC:1982.8) 20 OUT &H87,&H80 30 CLK=3993600/32 40 FRQ=CLK/261 'o4c 100 CS=0:REG=7:DAT=&H38:GOSUB 500 110 CS=0:REG=0:DAT=FRQ AND 255:GOSUB 500 120 CS=0:REG=1:DAT=(FRQ AND &HFF00)/256:GOSUB 500 130 CS=0:REG=8:DAT=15:GOSUB 500 180 PRINT"PUSH SPACE TO STOP" 190 IF INP(9)<>&HBF THEN 190 200 CS=0:REG=8:DAT=0:GOSUB 500 400 END 500 'write PSG ChipSelect=0/1/2/3 510 OUT &H84,REG 520 OUT &H85,&H3*(4^CS) 530 OUT &H85,0 540 OUT &H84,DAT 550 OUT &H85,&H2*(4^CS) 560 OUT &H85,0 570 RETURN |
I/O ポート $D3 【PPI コントロール出力】 | ||
---|---|---|
bit | 7 | 1 |
bit | 6-5 | PortA, PortC上位4bitのモード選択 00=mode0 01=mode1 10=11=mode2 |
bit | 4 | PortA 0=出力 1=入力 |
bit | 3 | PortC上位4bit 0=出力 1=入力 |
bit | 2 | PortB, PortC下位4bitのモード選択 0=mode0 1=mode1 |
bit | 1 | PortB 0=出力 1=入力 |
bit | 0 | PortC下位4bit 0=出力 1=入力 |
I/O ポート $D1 【PPI ポート B 出力】 | ||
---|---|---|
bit | 7-0 | 1bit PCM データ |
IO_PPI_PORTA equ $D0 IO_PPI_PORTB equ $D1 IO_PPI_PORTC equ $D2 IO_PPI_CTRL equ $D3 ld a,PPI_MODE0_ACH | PPI_OUT_A | PPI_OUT_CH | PPI_MODE0_BCL | PPI_OUT_B | PPI_OUT_CL out (IO_PPI_CTRL),a ld hl,PCMDATA ld de,PCMEND - PCMDATA ld c,IO_PPI_PORTB .loop: ld b,(hl) ;7 inc hl ;6 srl b srl b srl b ;b=0-31 ld a,$FF ;7 out (c),a ;12 ld a,32 ;7 sub b ;4 inc b ;4 djnz $ out (c),b ;12 ld b,a ;4 djnz $ dec de ;6 ld a,d ;4 or e ;4 jp nz,.loop ;10 |
|
|
|
10 ' ASCII Music Addapter SN76489 TEST 20 PT=&H10 30 F=3579545/32/261 'o4c 40 CH=0:V=0 :D=&H80+CH*32+16+V:GOSUB 110 50 CH=0:D=&H80+CH*32+(F AND 15):GOSUB 110 60 CH=0:D=(F AND &H3F0)/16:GOSUB 110 70 PRINT"PUSH SPACE TO STOP" 80 IF INP(9)<>191 THEN 80 90 CH=0:D=&H80+CH*32+16+15:GOSUB 110 100 END 110 OUT &H40,0:OUT PT,D:OUT &H40,1:RETURN |
|
di ld hl,PCMDATA ld de,PCMEND - 1 ld c,$10 .loop: outi ;16 ld b,33 ;7 djnz $ ;13/8 [13*32+8=424] or a ;4 sbc hl,de ;15 add hl,de ;11 jp nz,.loop ;10 ei |
|
ld hl,PCMDATA ld de,PCMEND - PCMDATA .loop: ld a,(hl) rrca rrca rrca and %00001110 bit 7,(hl) jr z,.skip inc a .skip: or %11010000 ;$D0 と or を取る ex af,af' .wait1: in a,($40) rrca ;port ready であれば待つ jr nc,.wait1 .wait2: in a,($40) rrca ;port busy であれば待つ jr c,.wait2 ex af,af' out ($10),a inc hl dec de ld a,d or e jp nz,.loop xor a out ($10),a |
|
ld hl,PCMDATA ;8bit 8192Hz ld de,PCMEND - PCMDATA ld c,$10 .loop: ld b,(hl) ;7 inc hl ;6 srl b srl b srl b ;b=0-31 ld a,$FF ;7 out (c),a ;12 ld a,32 ;7 sub b ;4 inc b ;4 djnz $ out (c),b ;12 ld b,a ;4 djnz $ dec de ;6 ld a,d ;4 or e ;4 jp nz,.loop ;10 jr Main |