;
; Copyright (c) 2018 Yosuke Sugahara. All rights reserved.
;
; Redistribution and use in source and binary forms, with or without
; modification, are permitted provided that the following conditions
; are met:
; 1. Redistributions of source code must retain the above copyright
; notice, this list of conditions and the following disclaimer.
; 2. Redistributions in binary form must reproduce the above copyright
; notice, this list of conditions and the following disclaimer in the
; documentation and/or other materials provided with the distribution.
;
; THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
; IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
; OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
; IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
; INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
; BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
; AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
; OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
; OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
; SUCH DAMAGE.
;
;
; LUNA XP multiplexed device firmware
;
; used language:
; zasm 4.1
; http://k1.spdns.de/Develop/Projects/zasm
;
; XP memory map
;
; type : SH, PR, IN, NC
; SH: host shared memory, 64kB, PA 00000 - 0FFFF
; PR: private memory, 32kB, PA 28000-2FFFF
; IN: HD647180 internal 512 bytes memory
; NC: not connected (00 or FF or image readable, maybe)
;
; start end type desc
; 0000 00FF SH RESET/RST etc.
; 0100 01FF SH shared variables
; 0200 0FFF SH resident program
; 1000 7FFF SH PAM/PCM buffer 28K
; 8000 8FFF SH PSG buffer 4K
; 9000 9FFF SH LPR buffer 4K
; A000 DFFF SH FDC buffer 16K
; E000 EFFF PR program/stack
; F000 FDFF NC bus error (00 or FF)
; FE00 FFDF IN PAM player
; FFE0 FFFF IN interrupt vector
;
; shared variable area
; 0100 XPBUS
; 0110 TIME
; 0120 PAM
; 0130 PCM
; 0140 PSG
; 0150 SPK
; 0160 LPR
; 0170 FDC
; 0180 SIO0
; 0190 SIO1
; device ID = bit 7-4
;
; XP internal device usage
; PRT0 device dispatcher/TIME
; PRT1 PCM
; PT2 unused
; ASCI0 SIO0
; ASCI1 SIO1 本体表記の関係で、入れ替える?
;
; READY-CMD-RESULT-RUN プロトコル
; XP 視点
; READY
; コマンドを受け付けできるとき != 0
; 受付できないとき 0
; CMD
; ホスト側が送信してくるコマンド
; コマンドなしは 0
; XP がコマンドを受け付けると、READY=0 CMD=0 の順で、XP が 0 にする
; RESULT
; コマンド実行結果。
; RESULT=x READY=1 の順で書き込む。
; ハードリセット、またはホストが 0 クリアする。
; RUN
; コマンド実行中は != 0
; 実行していないときは 0
; 実行完了時、RESULT=x RUN=0 READY=1 の順で書き込む。
;
; 通常シーケンス
; READY を上げる
; CMD の立ち上がりを待つ
; READY を下げる
; RUN を上げる
; CMD を下げる
; 実行
; RESULT を書く
; RUN を下げる
; READY を上げる
;
; ホスト視点
; 実行完了を待つとき
; while (READY == 0); // 受付可能待ち
; RESULT=0; // 結果クリア
; CMD=x; // コマンド送信
; while (RESULT == 0); // 実行完了待ち
; if (RESULT==ERROR) error(); // エラー確認
;
;
; XPBUS
; +0.b READY
; +1.b CMD
; +2.b RESULT
; +3.b RUN
;
; +4.b STAT_RESET
; ファームウェア転送で 0 にされる。
; リセット位置の実行のたびに +1
; すなわち何もなければ 1 になっている。
; +5.3 align
; +8.w PRT0_TIMER
; ==256(1200Hz)
; +A.w INTR1_DEV
; bitmap of INTR1 device ID
; +C.w INTR5_DEV
; bitmap of INTR5 device ID
;
; TIME
; +0.b READY
; +1.b CMD
; +2.b RESULT
; +3.b RUN
;
; +4.w TIMECOUNTER
;
; PAM
; +0.b READY
; +1.b CMD
; +2.b RESULT
; +3.b RUN
;
; +4.b ENC
; エンコードフォーマット識別子。
; +5.b REPT
; REPT 回数。
; +6.w CYCLE_CLK
; 基準クロック数
; クエリで返される。
; +8.b REPT_CLK
; 1 REPT あたりのクロック数。
; クエリで返される。
; +9.b REPT_MAX
; REPT に設定できる最大値。
; クエリで返される。
;
; +E.w STAT_PTR
;
; PCM
; +0.b READY
; +1.b CMD
; +2.b RESULT
; +3.b RUN
; +4.b ENC
; +6.w PRT1_TIMER
; PCM >=10(30.72kHz,200clk)
;
; +E.w STAT_PTR
;
; PSG
; +0.b READY
; +1.b CMD
; +2.b RESULT
; +3.b RUN
;
; SPK
; +0.b READY
; +1.b CMD
; +2.b RESULT
; +3.b RUN
;
; +4.b VOL
; PSG ボリュームレジスタ値。
; +6.w FREQ
; PSG FREQ レジスタ値。
; +8.w TIME
; 1200Hz 単位の持続時間。
; +A.w REMAIN
; 内部変数:残り時間。
;
; LPR
; TBD.
; FDC
; TBD.
;
; SIO0
; +0.b READY
; +1.b CMD
; +2.b RESULT
; +3.b RUN
; ; 送受信のバッファリングも検討したが
; ; わりに合わない
; +4.b TXCMD
; +5.b TXSTAT
; +6.b TX
; +A.b RXCMD
; +B.b RXSTAT
; +C.b RX
;
; SIO1
; +0.b READY
; +1.b CMD
; +2.b RESULT
; +3.b RUN
; ; 送受信のバッファリングも検討したが
; ; わりに合わない
; +4.b TXCMD
; +5.b TXSTAT
; +6.b TX
; +A.b RXCMD
; +B.b RXSTAT
; +C.b RX
.Z180
; ######## device ID
#define DEVID_XPBUS 0
#define DEVID_TIME 1
#define DEVID_PAM 2
#define DEVID_PCM 3
#define DEVID_PSG 4
#define DEVID_SPK 5
#define DEVID_LPR 6
#define DEVID_FDC 7
#define DEVID_SIO0 8
#define DEVID_SIO1 9
; ######## define
#define PAM_CMD_START 1
#define PAM_CMD_QUERY 2
#define PAM_ENC_PAM2A 1
#define PAM_ENC_PAM2B 2
#define PAM_ENC_PAM3A 3
#define PAM_ENC_PAM3B 4
#define PAM_ENC_PAM1P 5
#define PCM_CMD_START 1
#define PCM_ENC_PCM1 1
#define PCM_ENC_PCM2 2
#define PCM_ENC_PCM3 3
#define SPK_CMD_START 1
#define SPK_CMD_STOP 2
#define SPK_CMD_KEEP 3
; #### RESULT
#define XPLX_R_OK 1
#define XPLX_R_ERROR_PARAM 254
#define XPLX_R_UNKNOWN_CMD 255
; ######## switch
; 0 = USE STAT_PTR for userland test mode
; 1 = USE HOSTINTR for kernel (normal)
#define USE_INTR 1
; ######## constants
; xp to host level 1 interrupt port
HOSTINTR1 .EQU 0B0H
; xp to host level 5 interrupt port
HOSTINTR5 .EQU 0A0H
; PAM use HOSTINTR5
PAM_HOSTINTR .EQU HOSTINTR5
; PCM use HOSTINTR5
PCM_HOSTINTR .EQU HOSTINTR5
; I/O PORT
TMDR0L .EQU 0CH
TMDR0H .EQU 0DH
RLDR0L .EQU 0EH
RLDR0H .EQU 0FH
TCR .EQU 10H
TMDR1L .EQU 14H
TMDR1H .EQU 15H
RLDR1L .EQU 16H
RLDR1H .EQU 17H
PSG_ADR .EQU 83H ; PSG address (out)
PSG_DAT .EQU 82H ; data output
PSG_IN .EQU 83H ; data input (in)
INITIAL_SP: .EQU 01000H
PRIVATE_SP: .EQU 0F000H
; ######## macros
ADD_HL_A: .MACRO
ADD A,L
LD L,A
JR NC,$ + 3
INC H
.ENDM
WAIT3 .MACRO
NOP
.ENDM
WAIT4 .MACRO
LD A,A
.ENDM
WAIT6 .MACRO
NOP
NOP
.ENDM
WAIT7 .MACRO
LD A,A ; 4+3=7
NOP
.ENDM
WAIT8 .MACRO
LD A,A ; 4*2=8
LD A,A
.ENDM
WAIT9 .MACRO
NOP ; 3*3=9
NOP
NOP
.ENDM
WAIT10 .MACRO
LD A,A ; 4+3*2=10
NOP
NOP
.ENDM
WAIT11 .MACRO
LD A,A ; 4*2+3=11
LD A,A
NOP
.ENDM
WAIT12 .MACRO
LD A,A ; 4*3=12
LD A,A
LD A,A
.ENDM
WAIT13 .MACRO
LD A,A ; 4+3*3=13
NOP
NOP
NOP
.ENDM
WAIT16 .MACRO
LD A,A
LD A,A
LD A,A
LD A,A
.ENDM
WAIT17 .MACRO
LD A,A ; 4*2+3*3=17
LD A,A
NOP
NOP
NOP
.ENDM
WAIT19 .MACRO
LD A,A ; 4*4+3=19
LD A,A
LD A,A
LD A,A
NOP
.ENDM
; ######## RESET/RST
.ORG 0000H
RESET:
JP ENTRY
.ORG 0038H
INT0:
JP INTR_INT0
.ORG 0066H
NMI:
RETN
.ORG 0080H
DEBUG0:: .DB 0
DEBUG1:: .DB 0
DEBUG2:: .DB 0
DEBUG3:: .DB 0
DEBUG4:: .DB 0
DEBUG5:: .DB 0
DEBUG6:: .DB 0
DEBUG7:: .DB 0
DEBUG8:: .DB 0
DEBUG9:: .DB 0
DEBUG10:: .DB 0
.ORG 00FCH
XPLX_MAGIC:: ; MAGIC
.DB "XPLX"
; ######## shared variables
; XPBUS
.ORG 0100H
XPLX_VAR_BASE::
XPBUS_READY::
.DB 0
XPBUS_CMD::
.DB 0
XPBUS_RESULT::
.DB 0
XPBUS_RUN::
.DB 0
XPBUS_STAT_RESET:: ; reset count
.DB 0
.DB 0,0,0 ; reserved
XPBUS_PRT0_TIMER:: ; PRT0 TIMER TLDR (devices dispatch)
.DW 256
XPBUS_INTR1_DEV:: ; HOSTINTR1 device
.DW 0
XPBUS_INTR5_DEV:: ; HOSTINTR5 device
.DW 0
; TIME
.ORG 0110H
TIME_READY::
.DB 0
TIME_CMD::
.DB 0
TIME_RESULT::
.DB 0
TIME_RUN::
.DB 0
TIME_TIMECOUNTER:: ; timecounter (TBD.)
.DW 0
; PAM
.ORG 0120H
PAM_READY::
.DB 0
PAM_CMD::
.DB 0
PAM_RESULT::
.DB 0
PAM_RUN::
.DB 0
PAM_ENC::
.DB 0
PAM_REPT::
.DB 0
PAM_CYCLE_CLK::
.DW 0
PAM_REPT_CLK::
.DB 0
PAM_REPT_MAX::
.DB 0
.DB 0,0,0,0 ; reserved
PAM_STAT_PTR::
.DW 0
; PCM
.ORG 0130H
PCM_READY::
.DB 0
PCM_CMD::
.DB 0
PCM_RESULT::
.DB 0
PCM_RUN::
.DB 0
PCM_ENC::
.DB 0
.DB 0 ; reserved
PCM_PRT1_TIMER:: ; PRT1 TIMER TLDR (PCM)
.DW 0
.DB 0,0,0,0,0,0 ; reserved
PCM_STAT_PTR::
.DW 0
; PSG
.ORG 0140H
PSG_READY::
.DB 0
PSG_CMD::
.DB 0
PSG_RESULT::
.DB 0
PSG_RUN::
.DB 0
; SPK
.ORG 0150H
SPK_READY::
.DB 0
SPK_CMD::
.DB 0
SPK_RESULT::
.DB 0
SPK_RUN::
.DB 0
SPK_VOL::
.DB 0
.DB 0 ; reserved
SPK_FREQ::
.DW 0
SPK_TIME::
.DW 0
SPK_REMAIN::
.DW 0
; LPR
.ORG 0160H
LPR_READY::
.DB 0
LPR_CMD::
.DB 0
LPR_RESULT::
.DB 0
LPR_RUN::
.DB 0
; TBD.
LPR_CMD_START .EQU 1
; FDC
.ORG 0170H
FDC_READY::
.DB 0
FDC_CMD::
.DB 0
FDC_RESULT::
.DB 0
FDC_RUN::
.DB 0
; TBD.
FDC_CMD_START .EQU 1
; SIO0
.ORG 0180H
SIO0_READY::
.DB 0
SIO0_CMD::
.DB 0
SIO0_RESULT::
.DB 0
SIO0_RUN::
.DB 0
SIO0_TXCMD::
.DB 0
SIO0_TXSTAT::
.DB 0
SIO0_TX::
.DB 0
.DS 3
SIO0_RXCMD::
.DB 0
SIO0_RXSTAT::
.DB 0
SIO0_RX::
.DB 0
; SIO1
.ORG 0190H
SIO1_READY::
.DB 0
SIO1_CMD::
.DB 0
SIO1_RESULT::
.DB 0
SIO1_RUN::
.DB 0
SIO1_TXCMD::
.DB 0
SIO1_TXSTAT::
.DB 0
SIO1_TX::
.DB 0
.DS 3
SIO1_RXCMD::
.DB 0
SIO1_RXSTAT::
.DB 0
SIO1_RX::
.DB 0
; ######## Bootstrap program
.ORG 0200H
ENTRY:
DI
LD SP,INITIAL_SP
; inc reset count
LD HL, XPBUS_STAT_RESET
INC (HL)
; initial devices
; READY=0
XOR A
LD (XPBUS_READY),A
LD (TIME_READY),A
LD (PAM_READY),A
LD (PCM_READY),A
LD (PSG_READY),A
LD (SPK_READY),A
LD (LPR_READY),A
LD (FDC_READY),A
LD (SIO0_READY),A
LD (SIO1_READY),A
LD A,1
LD (DEBUG0),A
; init XP internal devices
; internal I/O address = 00H - 3FH
LD A,00H ; IOA7[7]=0 IOSTP[5]=0
ICR .EQU 3FH
OUT0 (ICR),A
; memory wait = 0
; I/O wait = 3
; no DMA
LD A,20H ; MWI[76]=0 IWI[54]=2(3wait) DMS[32]=0 DIM[10]=0
DCNTL .EQU 32H
OUT0 (DCNTL),A
; disable refresh
LD A,03H ; REFE[7]=0 REFW[6]=0 CYC[10]=3(80state)
RCR .EQU 36H
OUT0 (RCR),A
LD A,2
LD (DEBUG0),A
; prepare memory map
; MMU
CBR .EQU 38H
BBR .EQU 39H
CBAR .EQU 3AH
; Common0: VA=0000H -> PA=00000H SH
; Bank : VA=E000H -> PA=28000H PR
; Common1: VA=F000H -> PA=FF000H IN
LD A,0FEH
OUT0 (CBAR),A
LD A,0F0H
OUT0 (CBR),A
LD A,1AH
OUT0 (BBR),A
LD A,3
LD (DEBUG0),A
; internal RAM addressing
; for no-wait access
; PA=FxxxxH にしたらノーウェイトになった。
; PA=0xxxxH だとウェイトが入った。
; ほかのアドレスは未調査。
; built-in RAM VA=FE00H PA=FFE00H
LD A,0F0H
RMCR .EQU 51H
OUT0 (RMCR),A
; disable external interrupt
; TODO: if use "Host to XP" interrupt, change here
LD A,00H ; TRAP[7]=0 ITE2[2]=0 ITE1[1]=0 ITE0[0]=0
ITC .EQU 34H
OUT0 (ITC),A
; Interrupt Vector Low = E
; I = FFH
; Interrupt Vector Address = FFE0H
LD A,0E0H
IL .EQU 33H
OUT0 (IL),A
LD A,0FFH
LD I,A
; interrupt mode 1
IM 1
LD A,4
LD (DEBUG0),A
CALL INIT_PSG
; TODO
; INIT FDC
; INIT LPR
; INIT SIO
; INIT PRT0,1
; TIE1[5]=TIE0[4]=0
; TOC1[3]=TOC0[2]=0
; TDE1[1]=TDE0[0]=0
LD A,00H
OUT0 (TCR),A
; prepare PRT0
LD HL,(XPBUS_PRT0_TIMER)
OUT0 (RLDR0L),L
OUT0 (TMDR0L),L
OUT0 (RLDR0H),H
OUT0 (TMDR0H),H
; TIE0, TID0 ON
; TIE0[4]=1 TDE0[0]=1
LD A,11H
OUT0 (TCR),A
; copy to private memory
LD HL,PROG_ORG
LD DE,PRIVATE_RAM
LD BC,PROG_ORG_LEN
LDIR
; interrupt vector copy to internal memory
LD HL,VECTOR_ORG
LD DE,VECTOR
LD BC,VECTOR_ORG_LEN
LDIR
LD A,5
LD (DEBUG0),A
; jump to XPBUS
JP XPBUS
; initialize PSG registers
; break all regs
INIT_PSG:
; init PSG
; PSG R0-R6 All 00H
LD A,0
LD B,7
LD C,PSG_DAT
LD D,0
PSG_CLEAR_06:
OUT (PSG_ADR),A
OUT (C),D
INC A
DJNZ PSG_CLEAR_06
; PSG mixer
; tone = off, noise = off
; IOA, IOB = output
LD A,7
LD D,0FFH
OUT (PSG_ADR),A
OUT (C),D
; PSG volume and envelope
; PSG R8-R15 all 0
LD A,8
LD B,8
LD D,0
PSG_CLEAR_8F:
OUT (PSG_ADR),A
OUT (C),D
INC A
DJNZ PSG_CLEAR_8F
; TODO: PSG I/O Port
RET
; ######## buffers
.PHASE 1000H
PAM_BUF::
PCM_BUF::
.DEPHASE
.PHASE 08000H
PAM_BUF_LEN:: .EQU $-PAM_BUF
PCM_BUF_LEN:: .EQU $-PCM_BUF
PSG_BUF::
.DEPHASE
.PHASE 09000H
PSG_BUF_LEN:: .EQU $-PSG_BUF
LPR_BUF::
.DEPHASE
.PHASE 0A000H
LPR_BUF_LEN:: .EQU $-LPR_BUF
FDC_BUF::
.DEPHASE
; ######## private memory program
.PHASE 0E000H
FDC_BUF_LEN:: .EQU $-FDC_BUF
PROG_ORG: .EQU $$
PRIVATE_RAM:
XPBUS:
LD A,6
LD (DEBUG0),A
LD SP,PRIVATE_SP
; devices READY=1
LD A,1
LD (XPBUS_READY),A
LD (TIME_READY),A
LD (PAM_READY),A
LD (PCM_READY),A
LD (PSG_READY),A
LD (SPK_READY),A
LD (LPR_READY),A
LD (FDC_READY),A
LD (SIO0_READY),A
LD (SIO1_READY),A
; wait for PRT0
EI
XPBUS_LOOP:
HALT
JR XPBUS_LOOP
INTR_PRT0:
; #### Periodic devices
; 1200Hz
; ここから呼び出される DISPATCH ルーチンは、
; o. A にコマンドが入っている
; o. AF, HL は破壊して良い。
; o. EI 状態で呼ばれることに注意。
; o. EI 状態でリターンすること。
; o. 裏レジスタは PCM 専用。
; o. PAM 以外、0.83 msec 以内にリターンすること。
PUSH AF
PUSH HL
LD A,7
LD (DEBUG0),A
; reset PRT0 interrupt
IN0 F,(TCR)
IN0 F,(TMDR0L)
; first EI, for PRT1
EI
TIMECOUNTER_INCR:
; timecounter
LD HL,(TIME_TIMECOUNTER)
INC HL
LD (TIME_TIMECOUNTER),HL
; #### XPBUS devices dispatcher
DEVICES_DISPATCH:
LD A,(XPBUS_CMD)
OR A
CALL NZ,XPBUS_DISPATCH
LD A,(PAM_CMD)
OR A
CALL NZ,PAM_DISPATCH
LD A,(PCM_CMD)
OR A
CALL NZ,PCM_DISPATCH
LD A,(PSG_CMD)
OR A
CALL NZ,PSG_DISPATCH
LD A,(SPK_CMD)
OR A
CALL NZ,SPK_DISPATCH
LD A,(LPR_CMD)
OR A
CALL NZ,LPR_DISPATCH
LD A,(FDC_CMD)
OR A
CALL NZ,FDC_DISPATCH
LD A,(SIO0_CMD)
OR A
CALL NZ,SIO0_DISPATCH
LD A,(SIO1_CMD)
OR A
CALL NZ,SIO1_DISPATCH
LD A,8
LD (DEBUG0),A
POP HL
POP AF
RETI
; #### XPBUS
XPBUS_DISPATCH:
; not implemented
XOR A
LD (XPBUS_CMD),A
LD A,XPLX_R_UNKNOWN_CMD
LD (XPBUS_RESULT),A
RET
; #### TIME
TIME_DISPATCH:
; not implemented
XOR A
LD (TIME_CMD),A
LD A,XPLX_R_UNKNOWN_CMD
LD (TIME_RESULT),A
RET
; #### PAM は末尾
; #### PCM driver core
; PCM 割り込みは裏レジスタを専有します。
; メインルーチン側では裏レジスタを使用してはいけません。
; #### PCM play start
PCM_DISPATCH:
CP PCM_CMD_START
JR Z,PCM_START
LD A,XPLX_R_UNKNOWN_CMD
PCM_ERROR:
LD (PCM_RESULT),A
RET
PCM_START:
; if READY==0 return
LD A,(PCM_READY)
OR A
RET Z
; check ENC
LD A,(PCM_ENC)
DEC A
JR Z,PCM_START_OK ; PCM1 = 1
DEC A
JR Z,PCM_START_OK ; PCM2 = 2
DEC A
JR Z,PCM_START_OK ; PCM3 = 3
LD A,XPLX_R_ERROR_PARAM
JR PCM_ERROR
PCM_START_OK:
; A = 0
LD (PCM_READY),A
LD (PCM_CMD),A
; prepare vector
DI
; set PRT1 vector
LD HL,PCM_INTR
LD (VEC_PRT1),HL
; prepare register
EXX
CALL INIT_PSG
; make interrupt handler
LD A,(PCM_ENC)
DEC A
JR Z,PCM_SET_PCM1
DEC A
JR Z,PCM_SET_PCM2
PCM_SET_PCM3:
LD HL,PCM3
JR PCM_SET
PCM_SET_PCM2:
LD HL,PCM2
JR PCM_SET
PCM_SET_PCM1:
LD HL,PCM1
PCM_SET:
LD (PCM_INTR_JMP),HL
LD HL,PCM_BUF
LD BC,0800H + PSG_ADR
LD DE,0709H
EXX
; TIE1, TDE1 OFF
IN0 A,(TCR)
AND 0DDH ; TIE1[5]=0 TDE1[1]=0
OUT0 (TCR),A
; prepare PRT1
LD HL,(PCM_PRT1_TIMER)
OUT0 (RLDR1L),L
OUT0 (RLDR1H),H
OUT0 (TMDR1L),L
OUT0 (TMDR1H),H
; TIE1, TID1 ON
OR 22H ; TIE1[5]=1 TDE1[5]=1
OUT0 (TCR),A
EI
LD A,1
LD (PCM_RUN),A
RET
; #### PCM interrupt handler
PCM_INTR:
; PRT1 interrupt
EX AF,AF
EXX
; interrupt acknowledge
; reset PRT1 Interrupt
IN0 F,(TCR)
IN0 F,(TMDR1L)
; ジャンプ先は書き換えられる
PCM_INTR_JMP: .EQU $+1
JP PCM1
PCM_INTR_NEXT:
RLCA
JR C,PCM_RELOAD
; inc ptr after reload check
INC HL
RLCA
JR C,PCM_STAT
RLCA
JR NC,PCM_NORMAL
; PCM RESET attention
; in: HL = EXIT address
PCM_RESET:
; PRT1 intr stop
IN0 A,(TCR)
; TIE1,TDE1 OFF
AND 0DDH ; TIE1[5]=0 TDE1[1]=0
OUT0 (TCR),A
; PLAY STOP
XOR A
LD (PCM_RUN),A
LD A,XPLX_R_OK
LD (PCM_RESULT),A
LD (PCM_READY),A
JR PCM_EXIT
; PCM common code
PCM_RELOAD:
LD HL,PCM_BUF
PCM_STAT:
#if USE_INTR
OUT (PCM_HOSTINTR),A
#else
LD (PCM_STAT_PTR),HL
#endif
PCM_NORMAL:
PCM_EXIT:
EXX
EX AF,AF
EI
RETI
; #### PCM core code
PCM1:
; PSG REG=8
OUT (C),B
; read attention or CH0
LD A,(HL)
OUT (PSG_DAT),A
JP PCM_INTR_NEXT
PCM2:
LD D,(HL)
INC HL
LD A,(HL)
OUT (C),B
OUT0 (PSG_DAT),D
OUT (C),E
OUT (PSG_DAT),A
JP PCM_INTR_NEXT
PCM3:
LD E,(HL)
INC HL
LD D,(HL)
INC HL
LD A,(HL)
PUSH HL
LD HL,090AH
OUT (C),B
OUT0 (PSG_DAT),E
OUT (C),H
OUT0 (PSG_DAT),D
OUT (C),L
OUT (PSG_DAT),A
POP HL
JP PCM_INTR_NEXT
; #### SPK
SPK_DISPATCH:
CP SPK_CMD_START
JR Z,SPK_START
CP SPK_CMD_STOP
JR Z,SPK_STOP
CP SPK_CMD_KEEP
JR Z,SPK_KEEP
LD A,XPLX_R_UNKNOWN_CMD
LD (SPK_RESULT),A
RET
SPK_START:
LD A,(SPK_READY)
OR A
RET Z
XOR A
LD (SPK_READY),A
; next to CMD_KEEP
LD A,SPK_CMD_KEEP
LD (SPK_CMD),A
LD A,1
LD (SPK_RUN),A
; set REMAIN
LD HL,(SPK_TIME)
LD (SPK_REMAIN),HL
DI
; PSG CH3 FREQ
LD HL,(SPK_FREQ)
LD A,4
OUT0 (PSG_ADR),A
OUT0 (PSG_DAT),L
LD A,5
OUT0 (PSG_ADR),A
OUT0 (PSG_DAT),H
; PSG CH3 VOL
LD A,10
OUT (PSG_ADR),A
LD A,(SPK_VOL)
OUT (PSG_DAT),A
; save PSG R7
LD A,7
OUT0 (PSG_ADR),A
IN A,(PSG_IN)
LD (SPK_PSGR7),A
; PSG CH3 TONE ON
AND 0FBH
OUT (PSG_DAT),A
JR SPK_EXIT
SPK_STOP:
LD A,(SPK_READY)
OR A
RET Z
SPK_STOP_CORE:
XOR A
LD (SPK_READY),A
LD (SPK_CMD),A
DI
; restore PSG R7
LD A,7
OUT (PSG_ADR),A
LD A,(SPK_PSGR7)
OUT (PSG_DAT),A
; PSG CH3 VOL=0
LD A,10
OUT (PSG_ADR),A
XOR A
OUT (PSG_DAT),A
LD (SPK_RUN),A
JR SPK_EXIT
SPK_KEEP:
; REMAIN == 0, then stop
LD HL,(SPK_REMAIN)
LD A,H
OR L
JR Z,SPK_STOP_CORE
DEC HL
LD (SPK_REMAIN),HL
SPK_EXIT:
EI
LD A,XPLX_R_OK
LD (SPK_RESULT),A
LD (SPK_READY),A
RET
SPK_PSGR7:
.DB 0
; ######## PSG
PSG_DISPATCH:
; not implemented
XOR A
LD (PSG_CMD),A
LD A,XPLX_R_UNKNOWN_CMD
LD (PSG_RESULT),A
RET
; ######## LPR
LPR_DISPATCH:
; not implemented
XOR A
LD (LPR_CMD),A
LD A,XPLX_R_UNKNOWN_CMD
LD (LPR_RESULT),A
RET
; ######## FDC
FDC_DISPATCH:
; not implemented
XOR A
LD (FDC_CMD),A
LD A,XPLX_R_UNKNOWN_CMD
LD (FDC_RESULT),A
RET
; ######## SIO
SIO0_DISPATCH:
; not implemented
XOR A
LD (SIO0_CMD),A
LD A,XPLX_R_UNKNOWN_CMD
LD (SIO0_RESULT),A
RET
SIO1_DISPATCH:
; not implemented
XOR A
LD (SIO1_CMD),A
LD A,XPLX_R_UNKNOWN_CMD
LD (SIO1_RESULT),A
RET
INTR_INT0:
INTR_ASCI0:
INTR_ASCI1:
; TBD
EI
RETI
; #### PAM play start
PAM_DISPATCH:
CP PAM_CMD_START
JR Z,PAM_START
CP PAM_CMD_QUERY
JR Z,PAM_QUERY
XOR A
LD (PAM_CMD),A
LD A,XPLX_R_UNKNOWN_CMD
LD (PAM_RESULT),A
RET
; PAM ENC -> PAM Driver MAP address
; OUT: HL = MAP address
; if error, direct return to main routine
PAM_ENC_MAP:
LD A,(PAM_ENC)
OR A
JR Z,PAM_ERROR_ENC
DEC A
CP PAM_DRIVER_MAP_LEN / 16 ; 16 bytes / entry
JP NC,PAM_ERROR_ENC
ADD A,A ; A *= 16
ADD A,A
ADD A,A
ADD A,A
LD HL,PAM_DRIVER_MAP
ADD_HL_A
RET
PAM_ERROR_ENC:
POP HL ; discard caller PC
PAM_ERROR_PARAM:
LD A,XPLX_R_ERROR_PARAM
LD (PAM_RESULT),A
RET ; return to main
PAM_QUERY:
CALL PAM_ENC_MAP ; get ENC to MAP
LD A,(PAM_READY)
OR A
RET Z
XOR A
LD (PAM_READY),A
LD (PAM_CMD),A
PUSH BC
PUSH DE
LD BC,12 ; MAP offset 12 = CYCLE_CLK
ADD HL,BC
; CYCLE_CLK, REPT_CLK, REPT_MAX
LD DE,PAM_CYCLE_CLK
LD BC,4
LDIR
POP DE
POP BC
LD A,XPLX_R_OK
LD (PAM_RESULT),A
LD (PAM_READY),A
RET
PAM_START:
CALL PAM_ENC_MAP ; get ENC to MAP
LD A,15
ADD_HL_A ; HL points REPT_MAX
LD A,(PAM_REPT)
CP (HL)
JR Z,PAM_START_OK ; == OK
JR C,PAM_START_OK ; < OK
JR PAM_ERROR_PARAM
PAM_START_OK:
LD A,(PAM_READY)
OR A
RET Z
XOR A
LD (PAM_READY),A
LD (PAM_CMD),A
; never normal return
; PAM never EI
DI
CALL INIT_PSG
CALL PAM_ENC_MAP ; re- get ENC to MAP
; copy to internal RAM
LD DE,PAM_DRIVER
LD SP,HL ; SP = top of Map entry
POP HL ; HEAD
POP BC ; HEAD_LEN
LDIR
LD A,(PAM_REPT)
INC A ; DEC is not change CY
PAM_REPT_LOOP:
POP HL ; REPT
POP BC ; REPT_LEN
DEC A ; DEC is not change CY
JR Z,PAM_REPT_END
LDIR
DEC SP
DEC SP
DEC SP
DEC SP
JR PAM_REPT_LOOP
PAM_REPT_END:
POP HL ; TAIL
POP BC ; TAIL_LEN
LDIR
; buffer pointer
LD HL,PAM_BUF
#if USE_INTR
#else
LD (PAM_STAT_PTR),HL
#endif
; prefetch
LD SP,HL ; 4
POP DE
; I/O WAIT 3 -> 2
; PSG の address / write 時間 は 300ns なので、
; 1.8432 clock あればよいので 1 wait から設定できるはずだが、
; 2 wait に設定すると out 命令が 12 clock となり、
; 共有メモリに対する POP の 9+3=12 clock と一致して
; クロック整合を取りやすくなるため、2 wait に設定する。
; なお PSG の read は 400ns 必要なため、2 wait だとあやしい。
; また HOSTINTR 用の I/O への out で wait を満足するかどうかは
; 未確定だけど、HOSTINTR 機構はデータバスの値ではなく
; アドレスへの出力で動作するため、ウェイトに関係なく動作すると
; 期待してみる。
LD A,10H ; IWI[54]=1(2wait)
OUT0 (DCNTL),A
LD A,1
LD (PAM_RUN),A
LD A,8
OUT (PSG_ADR),A
LD C,PSG_DAT
JP PAM_DRIVER
PAM_RESET:
; XPBUS に制御を戻す
LD SP,PRIVATE_SP
; I/O WAIT 2 -> 3
LD A,20H ; IWI[54]=2(3wait)
OUT0 (DCNTL),A
CALL INIT_PSG
XOR A
LD (PAM_RUN),A
LD A,XPLX_R_OK
LD (PAM_RESULT),A
LD (PAM_READY),A
JP XPBUS
PAM_DRIVER_MAP:
; 16 bytes / entry
DW PAM2A_HEAD_ORG
DW PAM2A_HEAD_LEN
DW PAM2A_REPT_ORG
DW PAM2A_REPT_LEN
DW PAM2A_TAIL_ORG
DW PAM2A_TAIL_LEN
DW 204 ;CYCLE_CLK
DB 36 ;REPT_CLK
DB 37 ;REPT_MAX
DW PAM2B_HEAD_ORG
DW PAM2B_HEAD_LEN
DW PAM2B_REPT_ORG
DW PAM2B_REPT_LEN
DW PAM2B_TAIL_ORG
DW PAM2B_TAIL_LEN
DW 152 ;CYCLE_CLK
DB 24 ;REPT_CLK
DB 57 ;REPT_MAX
DW PAM3A_HEAD_ORG
DW PAM3A_HEAD_LEN
DW PAM3A_REPT_ORG
DW PAM3A_REPT_LEN
DW PAM3A_TAIL_ORG
DW PAM3A_TAIL_LEN
DW 298 ;CYCLE_CLK
DB 51 ;REPT_CLK
DB 24 ;REPT_MAX
DW PAM3B_HEAD_ORG
DW PAM3B_HEAD_LEN
DW PAM3B_REPT_ORG
DW PAM3B_REPT_LEN
DW PAM3B_TAIL_ORG
DW PAM3B_TAIL_LEN
DW 136 ;CYCLE_CLK
DB 36 ;REPT_CLK
DB 38 ;REPT_MAX
PAM_DRIVER_MAP_LEN: .EQU $-PAM_DRIVER_MAP
.DEPHASE
; ######## PAM drivers
.PHASE 0FE00H
; all PAM drivers have same address=0FE00H
PAM_DRIVER:
.DEPHASE
; #### PAM2A
.PHASE 0FE00H
PAM2A_HEAD_ORG: .EQU $$
PAM2A_HEAD:
PAM2A:
; PAM2A
; 12+0:12+12 = 1:2 PAM
; PAM 36clk 170.667kHz
; output PAM wave = normal 5 + antinoise 1
; 1 PAM cycle = 204 clk
; 6.144E6 / (204 + 36*n)
; sampling freqs:
; 0: 30118
; 37: 4000
; no STAT for first time
JP PAM2A_LOOP
PAM2A_RELOAD:
OUT (C),E
OUT (C),D
LD SP,PAM_BUF ;9
WAIT3
PAM2A_STAT:
#if USE_INTR
OUT (C),E
OUT (C),D
OUT (PAM_HOSTINTR),A ;10+2
#else
; STAT_PTR モードでの遅れはしょうがない
OUT (C),E
OUT (C),D
LD (PAM_STAT_PTR),SP ;19+3
#endif
PAM2A_NORMAL:
OUT (C),E
OUT (C),D
; prefetch
POP DE ;9+3
OUT (C),L
OUT (C),H
; うまくいくかはわからない
; 本来 wait 12 だが PAM 遷移ノイズを
; 低減するため待たない
PAM2A_LOOP:
; prefetched DE
OUT (C),E
OUT (C),D
; HL = DE for save current sample
LD L,E ;4
LD H,D ;4
; A = attention
LD A,E ;4
PAM2A_HEAD_LEN: .EQU $-PAM2A_HEAD
PAM2A_REPT_ORG: .EQU $$
PAM2A_REPT:
OUT (C),E
OUT (C),D
WAIT12
PAM2A_REPT_LEN: .EQU $-PAM2A_REPT
PAM2A_TAIL_ORG: .EQU $$
PAM2A_TAIL:
; このブロックは動的再配置されるので
; このブロック"への"ジャンプは困難
; "からの"ジャンプは可能。
OUT (C),E
OUT (C),D
RLCA
; attention bit
; bit7=1, reload
; must be JP
JP C,PAM2A_RELOAD ; jump=9 no=6
WAIT3
OUT (C),E
OUT (C),D
RLCA ; 3
; bit6=1, stat
; must be JP
JP C,PAM2A_STAT ; jump=9 no=6
WAIT3
OUT (C),E
OUT (C),D
RLCA ; 3
; bit5=0, normal
; must be JP
JP NC,PAM2A_NORMAL ; jump=9 no=6
; attention=001, reset
JP PAM_RESET
PAM2A_TAIL_LEN: .EQU $-PAM2A_TAIL
; cycle
; 5 * (12*3) + 12*2 = 204
.DEPHASE
; #### PAM2B
.PHASE 0FE00H
; all PAM drivers have same address=0FE00H
PAM2B_HEAD_ORG: .EQU $$
PAM2B_HEAD:
PAM2B:
; PAM2B
; averaged 1:1 PAM
; wait (4,7), (3,9), (9,12), (12,0)
; phase wait 28:28
; clk 35, 36, 45, 36
; PAM 176, 171, 137, 171 kHz
; output PAM wave = 4
; 1 PAM cycle = 152 clk
; 6.144E6 / (152 + 24*n)
; sampling freqs:
; 0: 40421
; 57: 4042
; no STAT for first time
JP PAM2B_LOOP
PAM2B_RELOAD:
OUT (C),E
LD SP,PAM_BUF ;9
PAM2B_STAT:
#if USE_INTR
OUT (C),D
OUT (PAM_HOSTINTR),A ;10+2
#else
; STAT_PTR モードでの遅れはしょうがない
OUT (C),D
LD (PAM_STAT_PTR),SP ;19+3
#endif
PAM2B_NORMAL:
OUT (C),E
; prefetch
POP DE ;9+3
OUT (C),B
PAM2B_LOOP:
; prefetched DE
OUT (C),E
; A = attention
LD A,E ;4
OUT (C),D
; B = save D
LD B,D ;4
WAIT3
PAM2B_HEAD_LEN: .EQU $-PAM2B_HEAD
PAM2B_REPT_ORG: .EQU $$
PAM2B_REPT:
OUT (C),E
OUT (C),D
PAM2B_REPT_LEN: .EQU $-PAM2B_REPT
PAM2B_TAIL_ORG: .EQU $$
PAM2B_TAIL:
; このブロックは動的再配置されるので
; このブロック"への"ジャンプは困難
; "からの"ジャンプは可能。
OUT (C),E
RLCA ;3
OUT (C),D
; attention bit
; bit7=1, reload
; must be JP
JP C,PAM2B_RELOAD ; jump=9 no=6
RLCA ; 3
OUT (C),E
; bit6=1, stat
; must be JP
JP C,PAM2B_STAT ; jump=9 no=6
RLCA ; 3
OUT (C),D
WAIT3
; bit5=0, normal
; must be JP
JP NC,PAM2B_NORMAL ; jump=9 no=6
; attention=001, reset
JP PAM_RESET
PAM2B_TAIL_LEN: .EQU $-PAM2B_TAIL
; cycle
; 4 * 12*2 + (4+7 + 3+9 + 9+12 + 12+0) = 152
.DEPHASE
; #### PAM3A
.PHASE 0FE00H
PAM3A_HEAD_ORG: .EQU $$
PAM3A_HEAD:
PAM3A:
; PAM3A
; 12+0:12+3:12+12 = 4:5:8 PAM
; PAM 51clk 120.471kHz
; output PAM wave = normal 5 + antinoise 1
; 1 PAM cycle = 298 clk
; 6.144E6 / (298 + 51*n)
; sampling freqs:
; 0: 20617
; 24: 4037
; prefetch
POP AF
LD B,A
; no STAT for first time
JP PAM3A_LOOP
PAM3A_RELOAD:
OUT (C),L
OUT (C),H
WAIT3
OUT (C),B
LD SP,PAM_BUF ;9
WAIT3
PAM3A_STAT:
#if USE_INTR
OUT (C),L
OUT (C),H
WAIT3
OUT (C),B
OUT (PAM_HOSTINTR),A ;10+2
#else
; STAT_PTR モードでの遅れはしょうがない
OUT (C),L
OUT (C),H
WAIT3
OUT (C),B
LD (PAM_STAT_PTR),SP ;19+3
#endif
PAM3A_NORMAL:
OUT (C),L
OUT (C),H
WAIT3
OUT (C),B
; prefetch
POP DE ;9+3
OUT (C),L
OUT (C),H
WAIT3
OUT (C),B
; prefetch
POP AF ;9+3
OUT (C),L
OUT (C),H
WAIT3
OUT (C),B
; うまくいくかはわからない
; 本来 wait 12 だが PAM 遷移ノイズを
; 低減するのも含めて4clkだけ消費する
LD B,A ;4
PAM3A_LOOP:
; prefetched DE, A=B
PAM3A_HEAD_LEN: .EQU $-PAM3A_HEAD
PAM3A_REPT_ORG: .EQU $$
PAM3A_REPT:
OUT (C),E
OUT (C),D
WAIT3
OUT (C),B
WAIT12
PAM3A_REPT_LEN: .EQU $-PAM3A_REPT
PAM3A_TAIL_ORG: .EQU $$
PAM3A_TAIL:
; このブロックは動的再配置されるので
; このブロック"への"ジャンプは困難
; "からの"ジャンプは可能。
OUT (C),E
OUT (C),D
EX DE,HL ;3
OUT (C),B
RLCA
; attention bit
; bit7=1, reload
; must be JP
JP C,PAM3A_RELOAD ; jump=9 no=6
WAIT3
OUT (C),L
OUT (C),H
WAIT3
OUT (C),B
RLCA ; 3
; bit6=1, stat
; must be JP
JP C,PAM3A_STAT ; jump=9 no=6
WAIT3
OUT (C),L
OUT (C),H
WAIT3
OUT (C),B
RLCA ; 3
; bit5=0, normal
; must be JP
JP NC,PAM3A_NORMAL ; jump=9 no=6
; attention=001, reset
JP PAM_RESET
PAM3A_TAIL_LEN: .EQU $-PAM3A_TAIL
; cycle
; 5 * (12*3+3+12) + (12*3+3+4) = 298
.DEPHASE
; #### PAM3B
.PHASE 0FE00H
PAM3B_HEAD_ORG: .EQU $$
PAM3B_HEAD:
PAM3B:
; PAM3B
; approx 1:1:1
; wait (9,9,12), (12,12,10)
; phase wait 21:21:22
; clk 66, 70
; PAM 93, 88 kHz
; output PAM wave = 2
; 1 PAM cycle = 136 clk
; 6.144E6 / (136 + 36*n)
; sampling freqs:
; 0: 45176
; 38: 4085
; prefetch
POP AF
LD B,A
RLCA
; no STAT for first time
JP PAM3B_LOOP
PAM3B_RELOAD:
OUT (C),D
LD SP,PAM_BUF ;9
PAM3B_STAT:
#if USE_INTR
OUT (C),B
OUT (PAM_HOSTINTR),A ;10+2
#else
; STAT_PTR モードでの遅れはしょうがない
OUT (C),B
LD (PAM_STAT_PTR),SP ;19+3
#endif
PAM3B_NORMAL:
OUT (C),E
; prefetch
POP HL ;9+3
OUT (C),D
; prefetch
POP AF ;9+3
OUT (C),B
EX DE,HL ;3
LD B,A ;4
RLCA ;3
PAM3B_LOOP:
; prefetched DE,B A=RLCA-ed flag
PAM3B_HEAD_LEN: .EQU $-PAM3B_HEAD
PAM3B_REPT_ORG: .EQU $$
PAM3B_REPT:
OUT (C),E
OUT (C),D
OUT (C),B
PAM3B_REPT_LEN: .EQU $-PAM3B_REPT
PAM3B_TAIL_ORG: .EQU $$
PAM3B_TAIL:
; このブロックは動的再配置されるので
; このブロック"への"ジャンプは困難
; "からの"ジャンプは可能。
OUT (C),E
; attention bit
; bit7=1, reload
; must be JP
JP C,PAM3B_RELOAD ; jump=9 no=6
RLCA ; 3
OUT (C),D
; bit6=1, stat
; must be JP
JP C,PAM3B_STAT ; jump=9 no=6
RLCA ; 3
OUT (C),B
WAIT3
; bit5=0, normal
; must be JP
JP NC,PAM3B_NORMAL ; jump=9 no=6
; attention=001, reset
JP PAM_RESET
PAM3B_TAIL_LEN: .EQU $-PAM3B_TAIL
.DEPHASE
; #### PAM1P
.PHASE 0FE00H
PAM1P_HEAD_ORG: .EQU $$
PAM1P_HEAD:
PAM1P:
; PAM1P
; PAM1P は正確にはPCMだが
; 動作方式はPAMに近いためこちら。
; Polyphase PCM
; 1 cycle = 87 clk
; 6.144E6 / (87 + 3*n)
; sampling freqs:
; 0: 70621
; 255: 7420
LD HL,PAM_BUF ;9
LD C,PSG_ADR
; initial CH0
LD A,8
OUT (PSG_ADR),A
; rotated next CH
LD B,9
LD DE,080AH
; no STAT for first time
JP PAM1P_LOOP
PAM1P_RELOAD:
LD HL,PAM_BUF ;9
PAM1P_STAT:
#if USE_INTR
OUT (PAM_HOSTINTR),A ;10+2
#else
; STAT_PTR モードでの遅れはしょうがない
LD (PAM_STAT_PTR),HL ;16+3
#endif
PAM1P_NORMAL:
; rotate B,E,D
LD A,B ;4
LD B,E ;4
LD E,D ;4
LD D,A ;4
OUT (C),B ;10+2
PAM1P_LOOP:
LD A,(HL) ;6+3
INC HL ;4
OUT (PSG_DAT),A ;10+2
PAM1P_HEAD_LEN: .EQU $-PAM1P_HEAD
PAM1P_REPT_ORG: .EQU $$
PAM1P_REPT:
WAIT3
PAM1P_REPT_LEN: .EQU $-PAM1P_REPT
PAM1P_TAIL_ORG: .EQU $$
PAM1P_TAIL:
; このブロックは動的再配置されるので
; このブロック"への"ジャンプは困難
; "からの"ジャンプは可能。
RLCA ;3
; attention bit
; bit7=1, reload
; must be JP
JP C,PAM1P_RELOAD ; jump=9 no=6
RLCA ; 3
; bit6=1, stat
; must be JP
JP C,PAM1P_STAT ; jump=9 no=6
RLCA ; 3
WAIT3
; bit5=0, normal
; must be JP
JP NC,PAM1P_NORMAL ; jump=9 no=6
; attention=001, reset
JP PAM_RESET
PAM1P_TAIL_LEN: .EQU $-PAM1P_TAIL
; cycle
; 63 + 12 + 12 = 87
.DEPHASE
PROG_ORG_LEN: .EQU $$-PROG_ORG
; #### interrupt vector
.PHASE 0FFE0H
VECTOR_ORG: .EQU $$
VECTOR:
VEC_INT1:
DW INTR_IGN
VEC_INT2:
DW INTR_IGN
VEC_PRT0:
DW INTR_PRT0
VEC_PRT1:
DW INTR_IGN
VEC_DMAC0:
DW INTR_IGN
VEC_DMAC1:
DW INTR_IGN
VEC_SIO:
DW INTR_IGN
VEC_ASCI0:
DW INTR_ASCI0
VEC_ASCI1:
DW INTR_ASCI1
VEC_PT2IN:
DW INTR_IGN
VEC_PT2OUT:
DW INTR_IGN
VEC_PT2OVF:
DW INTR_IGN
; 本当はここはベクタテーブルだが
; 使われることはないので押し込む。
INTR_IGN:
EI
RETI
VECTOR_ORG_LEN: .EQU $$-VECTOR_ORG
.DEPHASE
XPLX_FIRMWARE_LEN:: .EQU $