Hi!
I had found this source code in a Japanese website a few years ago but I had lost it thanks to a HDD failure.
Today I managed to find it again and thought it would be cool to share and preserve it here.
My intention is to use it in ROM hacking to add XE-1AP support to some MD games (especially some arcade ports) I like.
AFAIK this is the official driver distributed by Sharp to be used in the X68000 games with analog controller support.
The driver is written in 68000 assembly and it was apparently labelled and commented by this guy called "mor" in 2001.
Original Source Code by SHARP (1989) | File name: "AJOY.S" ("AJOY.X" after compilation)
Code:
*=======================================*
* request header
_RECORD_LENGTH equ (a5) *byte
_LOGICAL_CODE equ 1(a5) *byte
_COMMAND equ 2(a5) *byte
_STATUS_LO equ 3(a5) *byte
_STATUS_HI equ 4(a5) *byte
_RESERVE_AREA equ 5(a5) *8bytes
* init
_NMB_UNIT equ 13(a5) *byte
_BREAK_ADDRESS equ 14(a5) *long
_BPB_POINTER equ 18(a5) *long
* media check
_MEDIA_DISCRIPT equ 13(a5) *byte
_RETURN_VALUE equ 14(a5) *word
* read/write
_GET_DATA equ 13(a5) *byte
_TRANS_ADDRESS equ 14(a5) *long
_SECTOR equ 18(a5) *long
_BYTECOUNT equ 18(a5) *long
_START_SECTOR equ 22(a5) *long
*=======================================*
*=======================================*
* デバイスヘッダ
*=======================================*
RSVHEAD equ 64 *reserved header size
HEADER equ 22 *header size
DEVICE_HEADER:
dc.l -1 *device_header
dc.w $8000 *2|cooked mode, character device 固定
dc.l Strategy *4
dc.l Entry *4
DEVICE_NAME:
dc.b 'JOY ' *8★ここにデバイス名(8バイト)を書いて下さい。
ds.b RSVHEAD-HEADER
*=======================================*
packet: dc.l 0
CommandTable:
dc.l Initialize *★0 初期化
dc.l MediaCheck *★1 メディアチェック
dc.l BuildBpb *★2 BPBの作成
dc.l IoctrlInput *★3 IOCTL入力
dc.l Input *★4 INPUT
dc.l NdstrInput *★5 非破壊入力
dc.l InputStatus *★6 ステータスチェック
dc.l InputFlush *★7 入力バッファフラッシュ
dc.l Output *★8 OUTPUT
dc.l OutputVerify *★9 OUTPUT WITH VERIFY
dc.l OutputStatus *★10 ステータスチェック
dc.l OutputFlush *★11 出力バッファフラッシュ
dc.l IoctrlOutput *★12 IOCTL出力
*=======================================*
* ストラテジ エントリ
*=======================================*
Strategy:
move.l a5,packet
rts
*=======================================*
* 割り込み エントリ
*=======================================*
saverg reg d1-d7/a0-a6
Entry: movem.l saverg,-(sp)
move.l packet(pc),a5
moveq #0,d0
move.b _COMMAND,D0
cmpi.b #$c,d0
bhi CmdErr
lea CommandTable(pc),a0
lsl.w #2,d0
movea.l (a0,d0.w),a0
jmp (a0)
CmdErr:
move.w #$700d,d0 *★エラーコード
bra Return
Exit: clr.w d0
Return: move.l packet,a5
move.b d0,_STATUS_LO
lsr.w #8,d0
move.b d0,_STATUS_HI
movem.l (sp)+,saverg
rts
*=======================================*
* 処理ルーチン
*=======================================*
*=======================================*
* ★1 メディアチェック
*=======================================*
MediaCheck:
bra CmdErr
*=======================================*
* ★2 BPBの作成
*=======================================*
BuildBpb:
bra CmdErr
*=======================================*
* ★3 IOCTL入力
*=======================================*
IoctrlInput:
bra CmdErr
*=======================================*
* ★4 INPUT
*=======================================*
Input:
bra Exit
*=======================================*
* ★5 非破壊入力
*=======================================*
NdstrInput:
bra Exit
*=======================================*
* ★6 ステータスチェック
*=======================================*
InputStatus:
bra Exit *set status 00
*=======================================*
* ★7 入力バッファフラッシュ
*=======================================*
InputFlush:
bra Exit
*=======================================*
* ★8 OUTPUT
*=======================================*
Output:
bra Exit
*=======================================*
* ★9 OUTPUT WITH VERIFY
*=======================================*
OutputVerify:
bra Exit
*=======================================*
* ★10 ステータスチェック
*=======================================*
OutputStatus:
bra Exit
*=======================================*
* ★11 出力バッファフラッシュ
*=======================================*
OutputFlush:
bra Exit
*=======================================*
* ★12 IOCTL出力
*=======================================*
IoctrlOutput:
bra CmdErr
*=======================================*
* CHECK DATA
*=======================================*
dc.b 'Isimochi'
*=======================================*
* IOCS $F2
*
* in d0.l=$f2
* d1.w=MD
*---------------------------------------*
*MD=0 アナログジョイスティックデータを読み込む
* in a1.l=ジョイスティックデータを格納するアドレス(10バイト)
* +0 dc.w Stick Up/Down
* +2 dc.w Stick Left/Right
* +4 dc.w Throttle Up/Down
* +6 dc.w Option Up/Down
* +8 dc.w Trigger -|-|-|-|A|B|A'|B'|A+A'|B+B'|C|D|E1|E2|START|SELECT
* out d0.l=0...正常なデータ
* -1...データ受信に失敗
*---------------------------------------*
*MD=1 ジョイスティックのモードを切り替える
* in d2.w=0...デジタルジョイスティックモード
* 1...アナログジョイスティックモード
* -1...現在のモードを調べる
* out d0.l=現在の(設定前の)モード
*---------------------------------------*
*MD=2 アナログジョイスティック転送速度のセット
* in d2.w=0...最高速
* 1...1/2
* 2...1/3
* 3...1/4
* -1...現在の速度を調べる
* out d0.l=現在の(設定前の)速度
*---------------------------------------*
*=======================================*
savereg reg d1-d3/a0-a3
IOCS_F2:
movem.l savereg,-(sp)
cmp.w #3,d1
bcc IOCSF2_err
lsl.w #2,d1
movea.l IOCSF2_table(pc,d1.w),a0
jsr (a0)
bra IOCSF2_q
IOCSF2_err:
moveq #-1,d0 *d0.l = error code
IOCSF2_q:
movem.l (sp)+,savereg
rts
IOCSF2_table:
dc.l GetAjoy,SetJoyMode,SetJoySpeed
*=======================================*
* GET ANALOG-JOYSTICK DATA
*
* in a1.l = buffer address
* out d0.l = error flag
*=======================================*
_8255ADDR equ $e9a001
_PC4ON equ $09 *PC4 on
_PC4OFF equ $08 *PC4 off
_REQUEST equ _PC4OFF
_REQOFF equ _PC4ON
_LHBIT equ 5
_ACKBIT equ 6
_WAITLOOP equ 800 *waiting for joystick_ack (x2.2us)
*---------------------------------------*
_8255A reg (a0) *port A
_8255B reg 2(a0) *port B
_8255C reg 4(a0) *port C
_8255CTRL reg 6(a0) *control
*---------------------------------------*
ofs = -12
GetAjoy:
link a6,#ofs *buffer
move.w sr,-(sp)
or.w #$0700,sr *interrupt off
movea.l #_8255ADDR,a0 *a0.l = 8255 address
move.b #_REQOFF,_8255CTRL *request off
move.b #_REQUEST,_8255CTRL *request to analog_joystick
move.w #5,d2 *d2.w = loop counter
lea.l ofs(a6),a2 *a2.l = buffer address
lea.l req_table(pc),a3 *a3.l = request_table
*---------------------------------------*
AnaJoy_0:
move.w #_WAITLOOP,d0 (8) *wait loop
move.b (a3)+,_8255CTRL (16) *request off
AnaJoy_4:
btst #_LHBIT,_8255A (12)
dbeq d0,AnaJoy_4 (12/10) *if HIGH_level
bne AnaJoy_e (12) *if time_out
AnaJoy_1:
btst #_ACKBIT,_8255A (12)
dbeq d0,AnaJoy_1 (12/10) *if ACK off
bne AnaJoy_e (12) *if time_out
move.b _8255A,d1 (8)
and.w #$f,d1 (8)
move.b d1,(a2)+ (8) *set data to buffer
AnaJoy_2:
btst #_LHBIT,_8255A (12)
dbne d0,AnaJoy_2 (12/10) *if LOW_level
beq AnaJoy_e (12) *if time_out
AnaJoy_3:
btst #_ACKBIT,_8255A (12)
dbeq d0,AnaJoy_3 (12/10) *if ACK off
bne AnaJoy_e (12) *if time_out
move.b _8255A,d1 (8)
and.w #$f,d1 (8)
move.b d1,(a2)+ (8) *set data to buffer
dbra d2,AnaJoy_0 (12)
*---------------------------------------*
move.w (sp)+,sr *interrupt on
lea.l ofs(a6),a2 *a1.l = buffer address
move.b 10(a2),d0
lsl.w #4,d0
or.b (a2)+,d0
lsl.w #4,d0
or.b (a2)+,d0
move.w d0,8(a1) *set trigger
moveq #0,d0
move.b (a2)+,d0
lsl.w #4,d0
or.b 3(a2),d0
move.w d0,(a1)+ *set CH0
move.b (a2)+,d0
lsl.w #4,d0
or.b 3(a2),d0
move.w d0,(a1)+ *set CH1
move.b (a2)+,d0
lsl.w #4,d0
or.b 3(a2),d0
move.w d0,(a1)+ *set CH2
move.b (a2)+,d0
lsl.w #4,d0
or.b 3(a2),d0
move.w d0,(a1) *set CH3
moveq #0,d0 *not error
unlk a6
rts
*---------------------------------------*
AnaJoy_e:
moveq #-1,d0 *error !
move.w (sp)+,sr *interrupt on
unlk a6
rts
*=======================================*
* CHANGE JOYSTICK MODE
*
* in d2.w = 0...degital
* 1...analog
* -1...check mode
* out d0.l = now_mode
*=======================================*
SetJoyMode:
moveq #0,d0
move.w joy_mode(pc),d0 *d0.l = old_mode
tst.w d2
bmi SetJoyMode_q *if check_mode
beq SetDjoy *if degital
SetAjoy:
move.w #1,joy_mode
move.b #_PC4ON,_8255ADDR+6 *PC4 ON
rts
SetDjoy:
clr.w joy_mode
move.b #_PC4OFF,_8255ADDR+6 *PC4 OFF
SetJoyMode_q:
rts
*=======================================*
* SET JOYSTICK SPEED
*
* in d2.w = 0...Maximam speed
* 1...1/2
* 2...1/3
* 3...1/4
* minus...Check_speed
* out d0.l = now_speed
*=======================================*
SetJoySpeed:
moveq #0,d0
move.w joy_speed,d0 *d0.l = speed
tst.w d2
bmi SetJoySpeed_q *if check_speed
cmp.w #4,d2
blt SetJspeed_1 *if speed < 4
moveq #3,d2
SetJspeed_1:
move.w d2,joy_speed
moveq #_REQUEST,d1
lea.l req_table(pc),a0
tst.w d2
bne SetJspeed_2
moveq #_REQOFF,d1
SetJspeed_2:
move.b d1,(a0)+ *1st
subq.w #1,d2
bne SetJspeed_3
moveq #_REQOFF,d1
SetJspeed_3:
move.b d1,(a0)+ *2nd
subq.w #1,d2
bne SetJspeed_4
moveq #_REQOFF,d1
SetJspeed_4:
move.b d1,(a0)+ *3rd
subq.w #1,d2
bne SetJspeed_5
moveq #_REQOFF,d1
SetJspeed_5:
move.b d1,(a0) *4th
SetJoySpeed_q:
rts
*=======================================*
* WORK
*=======================================*
joy_mode:
dc.w 0
joy_speed:
dc.w 0
init_flag:
dc.w 0
*---------------------------------------*
req_table:
dc.b _REQUEST *1
dc.b _REQUEST *2
dc.b _REQUEST *3
dc.b _REQUEST *4
dc.b _REQOFF *5
dc.b _REQOFF *6
*=======================================*
* ★0 初期化
*=======================================*
Initialize:
tst.w init_flag
bne Exit *if 初期化済み
*=======================================*
* 常駐しない部分
*=======================================*
Break:
lea.l _BPB_POINTER,a2 *a2.l = parameter addr.
bsr InitMain
tst.l d0
bne CmdErr
move.l last_addr,_BREAK_ADDRESS
bra Exit *if not error
*=======================================*
InitMain:
move.w #-1,init_flag *初期化済み
pea ajoy_msg
dc.w $ff09 *_PRINT
addq.l #4,sp
bsr Parameter
tst.l d0
bne InitPara *if parameter error
move.w #$1f2,-(sp) *IOCS $F2
dc.w $ff35 *_INTVCG
addq.l #2,sp
cmp.l #$00ffffff,d0
bls InitExist *if driver が登録されている
pea IOCS_F2
move.w #$01f2,-(sp) *IOCS $F2
dc.w $ff25 *_INTVCS
addq.l #6,sp
move.w joy_mode,d2
bsr SetJoyMode
move.w joy_speed,d2
bsr SetJoySpeed
moveq #0,d0
rts
*--------------------------------------*
InitExist:
movea.l d0,a0
cmp.l #'Isim',-8(a0)
bne InitOther
cmp.l #'ochi',-4(a0)
bne InitOther
pea exist_msg
dc.w $ff09 *_PRINT
addq.l #4,sp
bra InitErr
InitOther:
pea other_msg
dc.w $ff09 *_PRINT
addq.l #4,sp
bra InitErr
*--------------------------------------*
InitPara:
pea parameter_msg
dc.w $FF09 *_PRINT
addq.l #4,sp
*--------------------------------------*
InitErr:
move.l #'****',DEVICE_NAME
moveq #-1,d0
rts
*=======================================*
* AJOY.X ENTRY
*=======================================*
AJOY:
bsr SuperOn
bsr InitMain
tst.l d0
blt AJOYerror *if error
bsr DeviceTop
bsr DeviceEnd
move.l #DEVICE_HEADER,(a0)
bsr SuperOff
move.l last_addr,d0
sub.l #DEVICE_HEADER,d0
move.w #0,-(sp) *exit code
move.l d0,-(sp) *keep length
dc.w $ff31 *_KEEPPR
AJOYerror:
bsr SuperOff
dc.w $ff00 *_EXIT
*=======================================*
DeviceTop:
movea.l #$6800,a0 *search addr.
lea.l nul_str,a1
DeviceTop_1:
move.b (a0)+,d0
cmp.b (a1),d0
bne DeviceTop_1 *if not 'N'
subq.l #1,a0
bsr EqualStr
addq.l #1,a0
tst.l d0
beq DeviceTop_1 *retry
move.l a0,d0
btst #0,d0
beq DeviceTop_1 *if addr_even > retry
cmpi.w #%1000_0000_0010_0100,-11(a0) *Char/IOCTRL_disable/RAWmode/NULdev
bne DeviceTop_1 *if not target_device > retry
lea.l -15(a0),a0 *a0.l = device header addr.
move.l a0,nuldev_addr *set addr.
rts
*=======================================*
DeviceEnd:
movea.l nuldev_addr,a0 *a0.l = device_driver addr.
DeviceEnd_1:
cmp.l #-1,(a0)
beq DeviceEnd_q
movea.l (a0),a0
bra DeviceEnd_1
DeviceEnd_q:
rts
*=======================================*
EqualStr:
movem.l a0-a1,-(sp)
EqualStr_1:
move.b (a1)+,d0
beq EqualStr_2 *if (a1) = 0
cmp.b (a0)+,d0
beq EqualStr_1 *next char
moveq #0,d0
bra EqualStr_q
EqualStr_2:
moveq #-1,d0
EqualStr_q:
movem.l (sp)+,a0-a1
rts
*========================================================*
* CHECK PARAMETER
*
* in a2.l = parameter addr.
*
*========================================================*
Parameter:
moveq #0,d0
tst.b (a2)+
beq Parameter_q *if non parameter
Parameter_1:
move.b (a2)+,d0
beq Parameter_q *if parameter end
cmp.b #' ',d0
beq Parameter_1 *if ' '
cmp.b #'-',d0
beq Parameter_2 *if '-'
cmp.b #'/',d0
beq Parameter_2 *if '/'
bra Parameter_e
*--------------------------------------*
Parameter_2:
move.b (a2)+,d0
beq Parameter_e *if parameter end > error
cmp.b #' ',d0
beq Parameter_2 *if ' '
cmp.b #'d',d0
beq ParameterD *if 'd'
cmp.b #'D',d0
beq ParameterD *if 'D'
cmp.b #'s',d0
beq ParameterS *if 's'
cmp.b #'S',d0
beq ParameterS *if 'S'
bra Parameter_e *error
*--------------------------------------*
ParameterD:
clr.w joy_mode *set joystick_mode
bra Parameter_1
*--------------------------------------*
ParameterS:
bsr ParaNumb
cmp.w #4,d0
bcc Parameter_e *if speed > 3
move.w d0,joy_speed *set speed
bra Parameter_1
*--------------------------------------*
Parameter_e:
moveq #-1,d0
rts
*--------------------------------------*
Parameter_q:
moveq #0,d0
rts
*--------------------------------------*
ParaNumb:
moveq #0,d0 *d0.l = number
moveq #0,d1 *d1.w = char
moveq #-1,d2 *d2.w = first flag
ParaNumb_1:
move.b (a2),d1
beq ParaNumb_q *end
cmp.b #' ',d1
bne ParaNumb_2 *if not ' '
tst.w d2
blt ParaNumb_1 *if first flag
bra ParaNumb_q *end
ParaNumb_2:
moveq #0,d2 *clear first_flag
sub.b #'0',d1
blt ParaNumb_q *if < '0'
cmp.b #9,d1
bgt ParaNumb_q *if > '9'
addq.l #1,a2 *increment addr.
mulu #10,d0
add.l d1,d0
cmp.l #$ffff,d0
bgt ParaNumb_e *if d0.l > $ffff
bra ParaNumb_1
ParaNumb_e:
moveq #0,d0
ParaNumb_q:
rts
*=======================================*
* CHANGE SUPERBISER MODE
*=======================================*
SuperOn:
clr.l -(sp)
dc.w $ff20 *_SUPER
addq.l #4,sp
move.l d0,ssp_buf
rts
SuperOff:
move.l ssp_buf(pc),-(sp)
dc.w $ff20 *_SUPER
addq.l #4,sp
rts
*=======================================*
ssp_buf:
dc.l 0
last_addr:
dc.l Break
nuldev_addr:
dc.l 0
nul_str:
dc.b 'NUL ',0
ajoy_msg:
dc.b 13,10
dc.b 'ANALOG JOYSTICK DRIVER for X68000 version 1.00',13,10
dc.b 'Copyright 1989 SHARP Corp.',13,10
dc.b 0
parameter_msg:
dc.b '使用法:AJOY [€<option€>]',13,10
dc.b ' €<option€>',13,10
dc.b ' /D デジタルジョイスティックモードで起動します。',13,10
dc.b ' /Sn 通信速度を指定します。(0~3:無指定の時は0)',13,10
dc.b 0
exist_msg:
dc.b 'AJOY.Xはすでに登録されています!',13,10
dc.b 0
other_msg:
dc.b 'IOCS($F2)はすでに使用されています!',13,10
dc.b 0
.end AJOY
Driver Application Sample by SHARP (1989) | File name: "AJ.C" ("AJ.X" after compilation)
Code:
/*
アナログジョイステイックを使うための簡単なプログラム
1989/05/20 CC AjoySmp.c /W でコンパイルの事
STARTボタンを押すと終了します
*/
short work[5];
/*
+0 DC.W Stick UP/DOWN
+2 DC.W Stick LEFT/RIGHT
+4 DC.W Throttle UP/DOWN
+6 DC.W Option UP/DOWN
+8 DC.W Trigger (0でON)
-|-|-|-|A|B|A'|B'|A+A'|B+B'|C|D|E1|E2|START|SELECT
15 0
out D0.L= 0...正常なデータ
-1...データ受信に失敗
*/
main()
{
screen(0,2,1,1); /* 256*256, 256 colors */
AjoyInit();
do {
if (AjoyGet(work)) { /* error check */
printf("Ajoy Error\n");
exit(1);
}
pset(work[1],work[0],work[2]);
} while(work[4] & 2);
screen(2,0,1,1);
}
AjoyInit()
{
#asm
*-------------------------------*
* アナログモードセット
*-------------------------------*
moveq #$f2,d0 *IOCS番号
moveq #1,d1 *MD
moveq #1,d2 *アナログモード
trap #15 *IOCSコール
*-------------------------------*
* 通信速度セット
*-------------------------------*
moveq #$f2,d0 *IOCS番号
moveq #2,d1 *MD
moveq #0,d2 *最高速
trap #15 *IOCSコール
#endasm
}
AjoyGet(pointer)
short *pointer;
{
#asm
moveq #$f2,d0 *IOCS番号
moveq #0,d1 *MD
move.l 8(A6),a1 *バッファアドレス
*8(A6) = pointer
trap #15 *IOCSコール
* tst.l d0 *エラー?
#endasm
}
Modified Source Code (2001) | File name: "AJOY.S" ("AJOY.X" after compilation)
Code:
*=======================================*
* ANALOG JOYSTICK DRIVER for X68000 version 1.00
* Copyright 1989 SHARP Corp.
*=======================================*
* 2001.1.24(Wed) modified by mor
* ・常駐解除(-r)を追加
* ・コマンドラインの TAB をスペースと同じ扱いにした
*=======================================*
* request header
_RECORD_LENGTH reg (a5) *byte
_LOGICAL_CODE reg 1(a5) *byte
_COMMAND reg 2(a5) *byte
_STATUS_LO reg 3(a5) *byte
_STATUS_HI reg 4(a5) *byte
_RESERVE_AREA reg 5(a5) *8bytes
* init
_NMB_UNIT reg 13(a5) *byte
_BREAK_ADDRESS reg 14(a5) *long
_BPB_POINTER reg 18(a5) *long
* media check
_MEDIA_DISCRIPT reg 13(a5) *byte
_RETURN_VALUE reg 14(a5) *word
* read/write
_GET_DATA reg 13(a5) *byte
_TRANS_ADDRESS reg 14(a5) *long
_SECTOR reg 18(a5) *long
_BYTECOUNT reg 18(a5) *long
_START_SECTOR reg 22(a5) *long
*=======================================*
*=======================================*
* デバイスヘッダ
*=======================================*
RSVHEAD equ 64 *reserved header size
HEADER equ 22 *header size
DEVICE_HEADER:
dc.l -1 *device_header
dc.w $8000 *2|cooked mode, character device 固定
dc.l Strategy *4
dc.l Entry *4
DEVICE_NAME:
NAME1: .equ 'JOY '
NAME2: .equ ' '
dc.l NAME1,NAME2 *8★ここにデバイス名(8バイト)を書いて下さい。
ds.b RSVHEAD-HEADER
*=======================================*
packet: dc.l 0
CommandTable:
@@: dc.w Initialize-@b *★0 初期化
dc.w MediaCheck-@b *★1 メディアチェック
dc.w BuildBpb-@b *★2 BPBの作成
dc.w IoctrlInput-@b *★3 IOCTL入力
dc.w Input-@b *★4 INPUT
dc.w NdstrInput-@b *★5 非破壊入力
dc.w InputStatus-@b *★6 ステータスチェック
dc.w InputFlush-@b *★7 入力バッファフラッシュ
dc.w Output-@b *★8 OUTPUT
dc.w OutputVerify-@b *★9 OUTPUT WITH VERIFY
dc.w OutputStatus-@b *★10 ステータスチェック
dc.w OutputFlush-@b *★11 出力バッファフラッシュ
dc.w IoctrlOutput-@b *★12 IOCTL出力
*=======================================*
* ストラテジ エントリ
*=======================================*
Strategy:
move.l a5,packet
rts
*=======================================*
* 割り込み エントリ
*=======================================*
saverg reg d1-d7/a0-a6
Entry: movem.l saverg,-(sp)
move.l packet(pc),a5
moveq #0,d0
move.b _COMMAND,D0
cmpi.b #$c,d0
bhi CmdErr
add.w d0,d0
move.w CommandTable(pc,d0.w),d0
jmp CommandTable(pc,d0.w)
MediaCheck:
BuildBpb:
IoctrlInput:
IoctrlOutput:
CmdErr:
move.w #$700d,d0 *★エラーコード
bra Return
Input:
NdstrInput:
InputStatus:
InputFlush:
Output:
OutputVerify:
OutputStatus:
OutputFlush:
Exit: clr.w d0
Return: move.l packet(pc),a5
move.b d0,_STATUS_LO
move.w d0,-(sp)
move.b (sp)+,_STATUS_HI
movem.l (sp)+,saverg
rts
*=======================================*
* CHECK DATA
*=======================================*
INAMEp: .equ 'mor1'
dc.l INAMEp
INAME1: .equ 'Isim'
INAME2: .equ 'ochi'
dc.l INAME1,INAME2
*=======================================*
* IOCS $F2
*
* in d0.l=$f2
* d1.w=MD
*---------------------------------------*
*MD=0 アナログジョイスティックデータを読み込む
* in a1.l=ジョイスティックデータを格納するアドレス(10バイト)
* +0 dc.w Stick Up/Down
* +2 dc.w Stick Left/Right
* +4 dc.w Throttle Up/Down
* +6 dc.w Option Up/Down
* +8 dc.w Trigger -|-|-|-|A|B|A'|B'|A+A'|B+B'|C|D|E1|E2|START|SELECT
* out d0.l=0...正常なデータ
* -1...データ受信に失敗
*---------------------------------------*
*MD=1 ジョイスティックのモードを切り替える
* in d2.w=0...デジタルジョイスティックモード
* 1...アナログジョイスティックモード
* -1...現在のモードを調べる
* out d0.l=現在の(設定前の)モード
*---------------------------------------*
*MD=2 アナログジョイスティック転送速度のセット
* in d2.w=0...最高速
* 1...1/2
* 2...1/3
* 3...1/4
* -1...現在の速度を調べる
* out d0.l=現在の(設定前の)速度
*---------------------------------------*
*=======================================*
savereg reg d1-d3/a0-a3
IOCS_F2:
movem.l savereg,-(sp)
cmp.w #3,d1
bcs @f
moveq #-1,d0 *d0.l = error code
bra IOCSF2_q
@@: add.w d1,d1
move.w IOCSF2_table(pc,d1.w),d1
jsr IOCSF2_table(pc,d1.w)
IOCSF2_q:
movem.l (sp)+,savereg
rts
IOCSF2_table:
@@: dc.w GetAjoy-@b
dc.w SetJoyMode-@b
dc.w SetJoySpeed-@b
*=======================================*
* GET ANALOG-JOYSTICK DATA
*
* in a1.l = buffer address
* out d0.l = error flag
*=======================================*
_8255ADDR equ $e9a001
_PC4ON equ $09 *PC4 on
_PC4OFF equ $08 *PC4 off
_REQUEST equ _PC4OFF
_REQOFF equ _PC4ON
_LHBIT equ 5
_ACKBIT equ 6
_WAITLOOP equ 800 *waiting for joystick_ack (x2.2us)
*---------------------------------------*
_8255A reg (a0) *port A
_8255B reg 2(a0) *port B
_8255C reg 4(a0) *port C
_8255CTRL reg 6(a0) *control
*---------------------------------------*
ofs = -12
GetAjoy:
link a6,#ofs *buffer
move.w sr,-(sp)
or.w #$0700,sr *interrupt off
movea.l #_8255ADDR,a0 *a0.l = 8255 address
move.b #_REQOFF,_8255CTRL *request off
move.b #_REQUEST,_8255CTRL *request to analog_joystick
move.w #5,d2 *d2.w = loop counter
lea.l ofs(a6),a2 *a2.l = buffer address
lea.l req_table(pc),a3 *a3.l = request_table
*---------------------------------------*
AnaJoy_0:
move.w #_WAITLOOP,d0 (8) *wait loop
move.b (a3)+,_8255CTRL (16) *request off
AnaJoy_4:
btst #_LHBIT,_8255A (12)
dbeq d0,AnaJoy_4 (12/10) *if HIGH_level
bne AnaJoy_e (12) *if time_out
AnaJoy_1:
btst #_ACKBIT,_8255A (12)
dbeq d0,AnaJoy_1 (12/10) *if ACK off
bne AnaJoy_e (12) *if time_out
* move.b _8255A,d1 (8)
* and.w #$f,d1 (8)
moveq #$0f,d1
and.b _8255A,d1 (8)
move.b d1,(a2)+ (8) *set data to buffer
AnaJoy_2:
btst #_LHBIT,_8255A (12)
dbne d0,AnaJoy_2 (12/10) *if LOW_level
beq AnaJoy_e (12) *if time_out
AnaJoy_3:
btst #_ACKBIT,_8255A (12)
dbeq d0,AnaJoy_3 (12/10) *if ACK off
bne AnaJoy_e (12) *if time_out
* move.b _8255A,d1 (8)
* and.w #$f,d1 (8)
moveq #$0f,d1
and.b _8255A,d1
move.b d1,(a2)+ (8) *set data to buffer
dbra d2,AnaJoy_0 (12)
*---------------------------------------*
move.w (sp)+,sr *interrupt on
lea.l ofs(a6),a2 *a1.l = buffer address
move.b 10(a2),d0
lsl.w #4,d0
or.b (a2)+,d0
lsl.w #4,d0
or.b (a2)+,d0
move.w d0,8(a1) *set trigger
moveq #0,d0
move.b (a2)+,d0
lsl.w #4,d0
or.b 3(a2),d0
move.w d0,(a1)+ *set CH0
move.b (a2)+,d0
lsl.w #4,d0
or.b 3(a2),d0
move.w d0,(a1)+ *set CH1
move.b (a2)+,d0
lsl.w #4,d0
or.b 3(a2),d0
move.w d0,(a1)+ *set CH2
move.b (a2)+,d0
lsl.w #4,d0
or.b 3(a2),d0
move.w d0,(a1) *set CH3
moveq #0,d0 *not error
unlk a6
rts
*---------------------------------------*
AnaJoy_e:
moveq #-1,d0 *error !
move.w (sp)+,sr *interrupt on
unlk a6
rts
*=======================================*
* CHANGE JOYSTICK MODE
*
* in d2.w = 0...digital
* 1...analog
* -1...check mode
* out d0.l = now_mode
*=======================================*
SetJoyMode:
moveq #0,d0
move.w joy_mode(pc),d0 *d0.l = old_mode
tst.w d2
beq SetDjoy *if digital
bmi SetJoyMode_q *if check_mode
SetAjoy:
move.w #1,joy_mode
move.b #_PC4ON,_8255ADDR+6 *PC4 ON
SetJoyMode_q:
rts
SetDjoy:
move.w d2,joy_mode
move.b #_PC4OFF,_8255ADDR+6 *PC4 OFF
rts
*=======================================*
* SET JOYSTICK SPEED
*
* in d2.w = 0...Maximam speed
* 1...1/2
* 2...1/3
* 3...1/4
* minus...Check_speed
* out d0.l = now_speed
*=======================================*
SetJoySpeed:
moveq #0,d0
move.w joy_speed(pc),d0 *d0.l = speed
tst.w d2
bmi SetJoySpeed_q *if check_speed
cmp.w #4,d2
blt SetJspeed_1 *if speed < 4
moveq #3,d2
SetJspeed_1:
move.w d2,joy_speed
moveq #_REQUEST,d1
lea.l req_table(pc),a0
tst.w d2
bne SetJspeed_2
moveq #_REQOFF,d1
SetJspeed_2:
move.b d1,(a0)+ *1st
subq.w #1,d2
bne SetJspeed_3
moveq #_REQOFF,d1
SetJspeed_3:
move.b d1,(a0)+ *2nd
subq.w #1,d2
bne SetJspeed_4
moveq #_REQOFF,d1
SetJspeed_4:
move.b d1,(a0)+ *3rd
subq.w #1,d2
bne SetJspeed_5
moveq #_REQOFF,d1
SetJspeed_5:
move.b d1,(a0) *4th
SetJoySpeed_q:
rts
*=======================================*
* WORK
*=======================================*
joy_mode:
dc.w 0
joy_speed:
dc.w 0
init_flag:
dc.w 0
*---------------------------------------*
req_table:
dc.b _REQUEST *1
dc.b _REQUEST *2
dc.b _REQUEST *3
dc.b _REQUEST *4
dc.b _REQOFF *5
dc.b _REQOFF *6
*=======================================*
* ★0 初期化
*=======================================*
Initialize:
move.w init_flag(pc),d0
bne Exit *if 初期化済み
*=======================================*
* 追加したワーク
* 実体は命令に上書きされるので、改造時は注意
* 必要なら .movea.l a0,a0 でも追加しましょう(nopだと060で遅い…って、ここでは関係ないか)
* ^HAS060の最適化を抑止
*=======================================*
old_vec:
*dc.l 0 * 旧ベクタ
*=======================================*
* 常駐しない部分
*=======================================*
Break: .equ old_vec+4
lea.l _BPB_POINTER,a2 *a2.l = parameter addr.
bsr InitMain
tst.l d0
bne CmdErr
move.l last_addr(pc),_BREAK_ADDRESS
bra Exit *if not error
*=======================================*
InitMain:
move.w #-1,init_flag *初期化済み
pea ajoy_msg(pc)
dc.w $ff09 *_PRINT
addq.l #4,sp
bsr Parameter
tst.l d0
bne InitPara *if parameter error
move.w #$1f2,-(sp) *IOCS $F2
dc.w $ff35 *_INTVCG
move.l d0,-(sp)
moveq #$f2,d2
cmp.b (sp),d2
addq.l #6,sp
beq @f
* cmp.l #$00ffffff,d0
* bls InitExist *if driver が登録されている
movea.l d0,a0
move.w (a0),d2
cmp.w InitMain_nulldrv(pc),d2 * rts だけなら登録されていない(?)
bne InitExist
@@:
bsr DeviceTop
bsr DeviceSearch
tst.l d0
bne DevExist *if driver は解放されているがデバイスドライバである
move.b rel_flag(pc),d0
bne InitNoExist
pea IOCS_F2(pc)
move.w #$01f2,-(sp) *IOCS $F2
dc.w $ff25 *_INTVCS
addq.l #6,sp
move.l d0,old_vec
move.w joy_mode(pc),d2
bsr SetJoyMode
move.w joy_speed(pc),d2
bsr SetJoySpeed
moveq #0,d0
InitMain_nulldrv:
rts
InitNoExist:
pea rel_noexist_msg(pc)
bra InitMes
*--------------------------------------*
InitExist:
movea.l d0,a0
cmpi.l #INAMEp,-12(a0)
bne InitOther
cmpi.l #INAME1,-8(a0)
bne InitOther
cmpi.l #INAME2,-4(a0)
bne InitOther
move.b rel_flag(pc),d0 * 常駐解除するか?
bne InitRelease
pea exist_msg(pc)
bra InitMes
InitOther:
pea other_msg(pc)
bra InitMes
InitRelease:
move.l old_vec-IOCS_F2(a0),-(sp)
move.w #$01f2,-(sp) *IOCS $F2
dc.w $ff25 *_INTVCS
addq.l #6,sp
bsr DeviceTop
bsr DeviceSearch
tst.l d0
bne InitRelease_1
pea (DEVICE_HEADER-240)-IOCS_F2(a0)
dc.w $ff49 *_MFREE
addq.l #4,sp
pea rel_msg(pc)
bra InitMes
InitRelease_1:
pea drel_msg(pc)
bra InitMes
*--------------------------------------*
DevExist:
movea.l d0,a0
lea IOCS_F2-DEVICE_HEADER(a0),a0
cmpi.l #INAMEp,-12(a0)
bne DevOther
cmpi.l #INAME1,-8(a0)
bne DevOther
cmpi.l #INAME2,-4(a0)
bne DevOther
move.b rel_flag(pc),d0
bne DevExist_1
pea (a0)
move.w #$01f2,-(sp) *IOCS $F2
dc.w $ff25 *_INTVCS
addq.l #6,sp
move.l d0,old_vec-IOCS_F2(a0)
move.w joy_mode(pc),d2
moveq #1,d1
moveq #$f2,d0
trap #15
move.w joy_speed(pc),d2
moveq #2,d1
moveq #$f2,d0
trap #15
moveq #-1,d0
rts
DevExist_1:
pea darel_msg(pc)
bra InitMes
DevOther:
pea devother_msg(pc)
bra InitMes
*--------------------------------------*
InitPara:
pea parameter_msg(pc)
InitMes:
dc.w $FF09 *_PRINT
addq.l #4,sp
*--------------------------------------*
InitErr:
move.l #'****',DEVICE_NAME
moveq #-1,d0
rts
*=======================================*
* AJOY.X ENTRY
*=======================================*
AJOY:
bsr SuperOn
bsr InitMain
tst.l d0
blt AJOYerror *if error
.ifdef USERDEV
bsr DeviceEnd
move.l #DEVICE_HEADER,(a0)
.endif
bsr SuperOff
move.l last_addr(pc),d0
sub.l #DEVICE_HEADER,d0
move.w #0,-(sp) *exit code
move.l d0,-(sp) *keep length
dc.w $ff31 *_KEEPPR
AJOYerror:
bsr SuperOff
dc.w $ff00 *_EXIT
*=======================================*
DeviceTop:
* in nul_str NULデバイスの名前
* out nuldev_addr NULデバイスのデバイスヘッダのアドレス
* break なし
movem.l d0/a0-a1,-(sp)
movea.l #$6800,a0 *search addr.
lea.l nul_str(pc),a1
DeviceTop_1:
move.b (a0)+,d0
cmp.b (a1),d0
bne DeviceTop_1 *if not 'N'
subq.l #1,a0
bsr EqualStr
addq.l #1,a0
tst.l d0
beq DeviceTop_1 *retry
move.l a0,d0
btst #0,d0
beq DeviceTop_1 *if addr_even > retry
cmpi.w #%1000_0000_0010_0100,-11(a0) *Char/IOCTRL_disable/RAWmode/NULdev
bne DeviceTop_1 *if not target_device > retry
lea.l -15(a0),a0 *a0.l = device header addr.
move.l a0,nuldev_addr *set addr.
movem.l (sp)+,d0/a0-a1
rts
*=======================================*
DeviceEnd:
* in nuldev_addr
* out a0 最後に登録されたデバイスドライバのデバイスヘッダ
* break なし
movea.l nuldev_addr(pc),a0 *a0.l = device_driver addr.
DeviceEnd_1:
cmp.l #-1,(a0)
beq DeviceEnd_q
movea.l (a0),a0
bra DeviceEnd_1
DeviceEnd_q:
rts
*=======================================*
DeviceSearch:
* in nuldrv_addr
* out d0 0:デバイスドライバでない !0:デバイスドライバである
* break なし
movem.l a0,-(sp)
movea.l nuldev_addr(pc),a0
moveq #-1,d0
1: cmpi.l #NAME1,DEVICE_NAME-DEVICE_HEADER(a0)
bne @f
cmpi.l #NAME2,4+DEVICE_NAME-DEVICE_HEADER(a0)
beq 8f
@@: movea.l (a0),a0
cmpa.l d0,a0
bne 1b
addq.l #1,a0
8: move.l a0,d0
9: movem.l (sp)+,a0
rts
*=======================================*
EqualStr:
* in a0,a1 string
* out d0 0:ne -1:eq
* break なし
movem.l a0-a1,-(sp)
EqualStr_1:
move.b (a1)+,d0
beq EqualStr_2 *if (a1) = 0
cmp.b (a0)+,d0
beq EqualStr_1 *next char
moveq #0,d0
bra EqualStr_q
EqualStr_2:
moveq #-1,d0
EqualStr_q:
movem.l (sp)+,a0-a1
rts
*========================================================*
* CHECK PARAMETER
*
* in a2.l = parameter addr.
*
*========================================================*
Parameter:
moveq #0,d0
tst.b (a2)+
beq Parameter_q *if non parameter
Parameter_1:
move.b (a2)+,d0
beq Parameter_q *if parameter end
bsr ParaSpc
beq Parameter_1
cmp.b #'-',d0
beq Parameter_2 *if '-'
cmp.b #'/',d0
beq Parameter_2 *if '/'
bra Parameter_e
*--------------------------------------*
Parameter_2:
move.b (a2)+,d0
beq Parameter_e *if parameter end > error
bsr ParaSpc
beq Parameter_2
ori.b #$20,d0 * to lower
cmp.b #'d',d0
beq ParameterD *if 'd'
cmp.b #'s',d0
beq ParameterS *if 's'
cmp.b #'r',d0
beq ParameterR *if 'r'
bra Parameter_e *error
*--------------------------------------*
ParameterR:
tas.b rel_flag *set rel_flag
bra Parameter_1
*--------------------------------------*
ParameterD:
clr.w joy_mode *set joystick_mode
bra Parameter_1
*--------------------------------------*
ParameterS:
bsr ParaNumb
cmp.w #4,d0
bcc Parameter_e *if speed > 3
move.w d0,joy_speed *set speed
bra Parameter_1
*--------------------------------------*
Parameter_e:
moveq #-1,d0
rts
*--------------------------------------*
Parameter_q:
moveq #0,d0
rts
*--------------------------------------*
ParaNumb:
moveq #0,d0 *d0.l = number
moveq #0,d1 *d1.w = char
moveq #-1,d2 *d2.w = first flag
ParaNumb_1:
move.b (a2),d1
beq ParaNumb_q *end
cmp.b #' ',d1
bne ParaNumb_2 *if not ' '
tst.w d2
blt ParaNumb_1 *if first flag
bra ParaNumb_q *end
ParaNumb_2:
moveq #0,d2 *clear first_flag
sub.b #'0',d1
blt ParaNumb_q *if < '0'
cmp.b #9,d1
bgt ParaNumb_q *if > '9'
addq.l #1,a2 *increment addr.
mulu #10,d0
add.l d1,d0
cmp.l #$ffff,d0
bgt ParaNumb_e *if d0.l > $ffff
bra ParaNumb_1
ParaNumb_e:
moveq #0,d0
ParaNumb_q:
rts
*--------------------------------------*
ParaSpc:
cmpi.b #' ',d0
beq @f
cmpi.b #9,d0
@@: rts
*=======================================*
* CHANGE SUPERBISER MODE
*=======================================*
SuperOn:
clr.l -(sp)
dc.w $ff20 *_SUPER
addq.l #4,sp
move.l d0,ssp_buf
rts
SuperOff:
move.l ssp_buf(pc),-(sp)
dc.w $ff20 *_SUPER
addq.l #4,sp
rts
*=======================================*
ssp_buf:
dc.l 0
last_addr:
dc.l Break
nuldev_addr:
dc.l 0
nul_str:
dc.b 'NUL ',0
rel_flag:
dc.b 0 * true:常駐解除
ajoy_msg:
dc.b 13,10
dc.b 'ANALOG JOYSTICK DRIVER for X68000 version 1.00',13,10
dc.b 'Copyright 1989 SHARP Corp.',13,10
dc.b 0
parameter_msg:
dc.b '使用法:AJOY [€<option€>]',13,10
dc.b ' €<option€>',13,10
dc.b ' /D デジタルジョイスティックモードで起動します',13,10
dc.b ' /Sn 通信速度を指定します(n=0~3:無指定時0)',13,10
dc.b ' /R 常駐解除します',13,10
dc.b 0
exist_msg:
dc.b 'AJOY.Xはすでに登録されています。',13,10,0
other_msg:
dc.b 'IOCS($F2)はすでに使用されています。',13,10,0
rel_msg:
dc.b 'AJOY.Xを常駐解除しました。',13,10,0
drel_msg:
dc.b 'デバイスドライバに登録されているAJOY.Xをシステムから切り離しました。',13,10,0
darel_msg:
dc.b 'デバイスドライバに登録されているAJOY.Xはすでにシステムから切り離されています。',13,10,0
rel_noexist_msg:
dc.b 'AJOY.Xは登録されていません。',13,10,0
devother_msg:
dc.b '異なるデバイスドライバが登録されています。',13,10,0
.end AJOY
Japanese Documentation by SHARP (1989):
Code:
==========================================================================================
◇ アナログジョイスティックドライバ for X68000 簡易説明書 ◇
==========================================================================================
ファイル名 AJOY.X
==========================================================================================
起動方法 コンフィグファイルに登録
Human68kコマンドモード 及び VShell 上から起動
==========================================================================================
起動時のオプション(コンフィグ・コマンドモードのどちらも共通)
/D デジタルジョイスティックモードで起動
省略時はアナログジョイスティックモード
/Sn 通信速度の指定
nは0~3(0が最高速)
省略時は0
------------------------------------------------------------------------------------------
CONFIG.SYS への登録
DEVICE = AJOY.X [/D][/Sn] (n:0~3)
------------------------------------------------------------------------------------------
コマンドモードからの起動
A>AJOY [/D][/Sn] (n:0~3)
==========================================================================================
ドライバの使い方
このドライバは起動されるとメモリ内に常駐し、以後IOCS($F2)で使用されます。
形式は一応デバイスドライバとなっており、’JOY’のデバイス名をもっていますが、
入出力及び、IOCTRLは使えません。
ジョイスティックモードとして、アナログモード・デジタルモードの2種類があり、
アナログモードではアナログジョイスティックしか、
デジタルモードではデジタルジョイスティックしか読むことはできません。
(X68000内の8255のPC4を切り替えるため)
また、アナログジョイスティックとの通信速度は4段階に切り替えることが可能ですが、
普段は最高速にしておいてください。(遅くしてもなんのメリットもありません。)
==========================================================================================
ドライバ使用上の注意
アナログジョイスティックはジョイスティック端子1に接続して下さい。(2は不可)
アナログジョイスティックとの通信中は割り込み禁止!になります。
割り込み禁止時間は以下の通りです。
(OTHERSはファミコン等の場合です。ここでは関係ありません。)
ATARI OTHERS
-------------------------
最高速 360~ 500 280~ 420
1/2 650~ 780 500~ 640
1/3 930~1070 730~ 870
1/4 1220~1360 920~1060 [μsec]
※X68000はATARIモードです。
==========================================================================================
IOCS($F2)の使い方
in D0.L=$F2
D1.L=MD[0~2]
他のレジスタはMDによって異なる
------------------------------------------------------------------------------------------
MD=0 アナログジョイスティックデータを読み込む
in A1.L=ジョイスティックデータを格納するアドレス(10バイト)
+0 DC.W Stick UP/DOWN
+2 DC.W Stick LEFT/RIGHT
+4 DC.W Throttle UP/DOWN
+6 DC.W Option UP/DOWN
+8 DC.W Trigger
-|-|-|-|A|B|A'|B'|A+A'|B+B'|C|D|E1|E2|START|SELECT
15 0
out D0.L= 0...正常なデータ
-1...データ受信に失敗
※スティックデータは0が左または上、255が右または下
トリガデータはビットが0でON、1でOFF
------------------------------------------------------------------------------------------
MD=1 ジョイスティックモードの変更
in D2.W= 0...デジタルジョイスティックモード
1...アナログジョイスティックモード
-1...現在のモードを調べる
out 現在(設定前)のモード
------------------------------------------------------------------------------------------
MD=2 アナログジョイスティック通信速度の変更
in D2.W= 0...最高速
1...1/2
2...1/3
3...1/4
-1...現在の速度を調べる
out 現在(設定前)の通信速度
※通信速度を最高速に設定した場合、アナログジョイスティックをリセットしないかぎり、
遅い速度への変更は行われない。
==========================================================================================
68000機械語プログラムの例
*===============================*
* 初期処理
*===============================*
*-------------------------------*
* アナログモードセット
*-------------------------------*
moveq #$f2,d0 *IOCS番号
moveq #1,d1 *MD
moveq #1,d2 *アナログモード
trap #15 *IOCSコール
*-------------------------------*
* 通信速度セット
*-------------------------------*
moveq #$f2,d0 *IOCS番号
moveq #2,d1 *MD
moveq #0,d2 *最高速
trap #15 *IOCSコール
*===============================*
* メイン処理
*===============================*
.
.
.
bsr AjoyGet *アナログジョイスティックデータの読み込み
.
.
.
*===============================*
* 終了処理
*===============================*
*-------------------------------*
* デジタルモードセット
*-------------------------------*
moveq #$f2,d0 *IOCS番号
moveq #1,d1 *MD
moveq #0,d2 *デジタルモード
trap #15 *IOCSコール
.
.
.
dc.w $ff00 *EXIT(OSに戻る)
*===============================*
* サブルーチン
*===============================*
AjoyGet:
moveq #$f2,d0 *IOCS番号
moveq #0,d1 *MD
lea joybuf,a1 *バッファアドレス
trap #15 *IOCSコール
tst.l d0 *エラー?
bmi AjoyErr *もしエラーならば
*-------------------------------*
* 正常時処理
*-------------------------------*
.
.
.
rts
*-------------------------------*
* エラー処理
*-------------------------------*
AjoyErr:
.
.
.
rts
*===============================*
* データバッファ
*===============================*
joybuf:
dc.w 0 *Stick U/D
dc.w 0 *Stick L/R
dc.w 0 *Trottle U/D
dc.w 0 *Option U/D
dc.w 0 *Trigger
==========================================================================================
<< アナログジョイスティック技術資料 >>
◆アナログチャンネルの割当
┌──────┬─────────────┐
│チャンネル0│Stick 上下方向 │
│チャンネル1│Stick 左右方向 │
│チャンネル2│Throttle 上下方向│
│チャンネル3│オプション │
└──────┴─────────────┘
◆アナログデータと動作方向
Stick・Throttle 上下方向
┌────────────────────┐
│ 方向 データ │
├────────────────────┤
│ │
│ 上 00H │
│ │
│ ↑ ↑ │
│ │
│ センター 80H or 7FH │
│ ^^^^^^^^^^^^^^^^^^^^^^ │
│ ↓ ↓ │
│ │
│ 下 FFH │
│ │
└────────────────────┘
Stick 左右方向
┌───────┬──────────────────┐
│ │ │
│ 方向 │ 左 ← センター → 右 │
│ │ │
│ │ │
│ データ │ 00H ← 80H → FFH │
│ │ or 7FH │
│ │ │
└───────┴──────────────────┘
◆アナログモード時のデータ
アナログチャンネルデータ
Data 7 6 5 4 3 2 1 0
┌─┬─┬─┬─┬─┬─┬─┬─┐
チャンネル0 8ビット └─┴─┴─┴─┴─┴─┴─┴─┘
1H ┃ 1L
┌─┬─┬─┬─┬─┬─┬─┬─┐
チャンネル1 8ビット └─┴─┴─┴─┴─┴─┴─┴─┘
2H ┃ 2L
┌─┬─┬─┬─┬─┬─┬─┬─┐
チャンネル2 8ビット └─┴─┴─┴─┴─┴─┴─┴─┘
3H ┃ 3L
┌─┬─┬─┬─┬─┬─┬─┬─┐
チャンネル3 8ビット └─┴─┴─┴─┴─┴─┴─┴─┘
4H ┃ 4L
トリガー入力データ
┌─┬─┬─┬─┬─┬─┬─┬─┬─┬─┐
10ビット└─┴─┴─┴─┴─┴─┴─┴─┴─┴─┘
A B C D┃E1 E2 F G┃A' B'
─────────────── F:Start
合計 42ビット G:Select
出力データビット構成
┌───┬──┬──┬──┬──┬──┬──┐
│IOA│ 6 │ 5 │ 3 │ 2 │ 1 │ 0 │
└───┼──┼──┼──┼──┼──┼──┤
│ ACK│ L/H│ D3 │ D2 │ D1 │ D0 │
┌───────┼──┼──┼──┼──┼──┼──┤
│1回目のACK│ 0 │ 0 │ A │ B │ C │ D │
├───────┼──┼──┼──┼──┼──┼──┤
│2回目 〃 │ 0 │ 1 │E1 │E2 │ F │ G │
├───────┼──┼──┼──┴──┴──┴──┤
│3回目 〃 │ 0 │ 0 │ 1 H │
├───────┼──┼──┼───────────┤
│4回目 〃 │ 0 │ 1 │ 2 H │
├───────┼──┼──┼───────────┤
│5回目 〃 │ 0 │ 0 │ 3 H │
├───────┼──┼──┼───────────┤
│6回目 〃 │ 0 │ 1 │ 4 H │
├───────┼──┼──┼───────────┤
│7回目 〃 │ 0 │ 0 │ 1 L │
├───────┼──┼──┼───────────┤
│8回目 〃 │ 0 │ 1 │ 2 L │
├───────┼──┼──┼───────────┤
│9回目 〃 │ 0 │ 0 │ 3 L │
├───────┼──┼──┼───────────┤
│10回目 〃 │ 0 │ 1 │ 4 L │
├───────┼──┼──┼──┬──┬──┬──┤
│11回目 〃 │ 0 │ 0 │ A │ B │ A'│ B'│
└───────┴──┴──┴──┴──┴──┴──┘
トリガー A,B,C,D,E1,E2,F,G =“0”;Trigger ON
=“1”;Trigger OFF
nチャンネル8ビットデータ = nH+nL
(例.1チャンネル8ビットデータ = 1H+1L)
◆コンピュータ・インターフェイス
1.Atari仕様 (X68000に接続の場合)
ジョイスティック1
ジョイコン側 X68000側
──────────────────────────────
PC4 : $E9A005 ポートのビット4(出力)
IOA 0~7 : $E9A001 8ビットポート (入力)
ジョイスティック2
ジョイコン側 X68000側
──────────────────────────────
PC4 : $E9A005 ポートのビット5(出力)
IOA 0~7 : $E9A003 8ビットポート (入力)
◆Atariデジタルモード
*アタリ仕様ポートと同様の方法でデータを得る。
PC4信号のLOW/HIGHにより、切り替えることにより12ビットデータ
を6ビットづつ2回に分けて読む事が可能。(通常はPC4=“0”)
┌─────┬────────────┬────────────┐
│ │ PC4=“0” │ PC4=“1” │
├─────┼────────────┼────────────┤
│IOA0 │ Stick UP │ Throt UP │
│IOA1 │ DOWN │ DOWN │
│IOA2 │ LEFT │ Trig C │
│IOA3 │ RIGHT │ D │
│IOA5 │ Trig A │ E1 │
│IOA6 │ B │ E2 │
└─────┴────────────┴────────────┘
◆Atariアナログモード
*4ビットデータバスの11回読み。
*REQをロウレベルにすることによりデータを要求し、ACKとL/H信号
ラインのレベルを監視しながらデータを取り込んでいく。
┌────────┬────────────────────┐
│ アタリ仕様信号 │ アナログモード信号の説明 │
├────────┼────────────────────┤
│ IOA0 │ D0 : データビット0 │
│ IOA1 │ D1 : 〃 1 │
│ IOA2 │ D2 : 〃 2 │
│ IOA3 │ D3 : 〃 3 │
│・・・・・・・・・・・・・・・・│・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・│
│ IOA5 │ L/H : データ切換信号 │
│ IOA6 │ ACK : データ確定信号 │
├────────┼────────────────────┤
│ PC4 │ REQ : データ要求割り込み信号 │
└────────┴────────────────────┘
◆転送速度(各サイクルタイム)
┌──────┬────┐
│ 最速モード │ 50 │
│ 1/2倍速 │ 96 │
│ 1/3倍速 │ 144 │
│ 1/4倍速 │ 192 │
└──────┴────┘
(単位:μsec)
ジョイコンはデータ転送要求(割り込み)によりデータ転送サイクルを6回繰り返す。
ジョイコンによるREQのレベルチェックは2,4,6,8回目のACKの立ち下が
りから2~6μsecの間で行っているので、コンピュータによるREQの立ち上げ
はこの間を避ける必要がある。
◆アナログジョイスティック使用上の注意事項
1.センター値は7FHまたは80Hとするが、±2の誤差をみておく。
2.調節モードにおいて、スティックとスロットルを入れ替えるとチャンネルに入力
されるアナログポートも入れ替わるため、調節しようとするチャンネルとトリガ
ーSW及び調節ボリュームとの関係に注意が必要。
3.アナログモードからデジタルモードに戻る際に8255ポートCのビット4と5
のレベルをロウレベルにしておかないとデジタルモードで動作不能になることが
ある。
Japanese Documentation by mor (2001):
Code:
AJOY.X v1.00 改造(1)版 2001.1.24(Wed)
X680x0 用に昔売られていた「サイバースティック」(とその互換品 XE-1AJ
・XE-1AP)専用ドライバの改造です。
使い方については純正付属の文書やサンプルを参照してください。
- 変更点 -
常駐解除(-r)できるようにしました。
ただし、CONFIG.SYS の DEVICE= 行で組み込んでいた場合はベクタの解放の
み行います。
コマンドラインから組み込んだ場合はデバイスドライバに登録しないように
しました。常駐時は IOCS $F2 のベクタ - 8 が 'Isimochi' になるので、そ
ちらでチェックしてください。
コマンドラインの TAB を半角スペースとして認識するようにしました。
ほんの少しだけ最適化しました。
- コメント -
アナログジョイスティックをデジタルモードにして、普通のデジタルジョイ
スティックとして使う限りは、AJOY.X の常駐は不要(普通に IOCS _JOYGET
したり I/O ポートを読めばいい)ですし、JOY STICK 2 に繋げても使えます。
IOCS $F2 のモード 0 はデジタルモードに対応していません。デジタルモー
ドではジョイスティックポートを直読みしましょう。(というか、デジタルモ
ードはただの ATARI 仕様のジョイスティックです。8255 の PC4 を操作しな
いとスティックと A/B ボタンしか認識できませんけれど…)
デジタルモード時のボタン割り当ては以下の通りです。(XE-1AP での実測)
スティック側 X680x0 側
------------- ----------------------------------------
スティック スティック
スロットル スロットル
A ボタン A ボタン
B ボタン B ボタン
A' ボタン A ボタン
B' ボタン B ボタン
C ボタン C ボタン
D ボタン D ボタン
E1 ボタン E1 ボタン
E2 ボタン E2 ボタン
START ボタン スティック左右と C,D ボタンの同時押し
SELECT ボタン スティック上下とスロットル上下の同時押し
XE-1AP(通称「カブトガニ」「土偶」)はスティック・スロットル共にセン
ター値がかなりあいまいです。
純正 AJOY.X 付属の AJOY_SUB.DOC には $7f or $80±2 と書かれています
が、そう決め打ちしないほうが多くの人を幸せにできるでしょう。
- 環境 -
AJOY.X v1.00 SHARP
HAS060 v3.09+87 Y.Nakamura/M.Kamada
HLK evolution v3.01+14 SALT/立花えり子
(敬称略)
- ライセンス関係 -
改造部分の著作権は放棄されています。日本国の法律上放棄できないとされ
ている部分については、それらを行使しないことで代用します。
無保証です。
改造部を含めた全体の取り扱いについては、純正 AJOY.X が PDS として公
開されているので自由に行って構わないと思います。
もしお持ちなら、純正のライセンスについては株式会社満開制作所発行の
「月刊電脳倶楽部(R)」14 号を参照してください。
この改造版に関する問い合わせは、以下までお願いします。
決して、(株)シャープなどの関連する個人や団体ほかに問い合わせないで
ください。
mailto:mor-g@geocities.co.jp
354 Mankai Special X680x0 user's Net
7480 サンデーネット
http://www.geocities.co.jp/SiliconValley-Bay/5160/
mor
Compressed archive containing the original driver release by SHARP:
https://drive.google.com/file/d/0B0c...ew?usp=sharing
Compressed archive containing the whole driver package by mor:
https://drive.google.com/file/d/0B0c...ew?usp=sharing
Studio Kamada ("X68000 Library") (Link to the original source release by the "Oh!X" publication):
http://retropc.net/x68000/software/h...ajoy/index.htm
mor's website ("X680x0 programs"):
http://mor.xps.jp/x6prg.html
Mega Drive to X68000 pinout info:
http://gamesx.com/wiki/doku.php?id=c...x68000_adapter
Basic reference about the controllers:
http://segaretro.org/XE-1_AP
http://gamesx.com/wiki/doku.php?id=x68000:cyber_stick
http://www.gamesx.com/wiki/doku.php?id=pcexe1apsoft
Cyber Stick Manual:
http://nfggames.com/x68000/Documenta...2%20Manual.pdf
XE-1AP Manual:
http://www.micomsoft.co.jp/develop/data/upfile/32-2.jpg
http://www.micomsoft.co.jp/develop/data/upfile/32-3.jpg
Cyber Stick Demo:
www.youtube.com/watch?v=skSrVIjy6OE (unboxing)
www.youtube.com/watch?v=y0KC5DeMbZU (PC Engine)
www.youtube.com/watch?v=k53n_gLeXQ4 (patched Space Harrier on the X68000)
www.youtube.com/watch?v=8vFYBaGzlcI (After Burner Complete on the Super 32X)
How to build a DB9-to-USB converter for the Cyberstick (in Japanese but has some pinout tables which may be useful):
http://www.sankichi.flnet.org/cyberstick_ab_1.html
http://www.sankichi.flnet.org/cyberstick_ab_2.html
Another way to build a DB9-to-USB converter for the Cyberstick, using the EZUSB-FX2 microcontroller:
http://d.hatena.ne.jp/nicotakuya/20080703/1215065367
http://nicotak.com/usb/cyberstick.zip (Cyber Stick + HID driver implemented in C for the EZUSB-FX2)
Some cool ads: http://x68030.web.fc2.com/x68k_khard_top.html
XE-1AP / Cyber Stick CZ-8NJ2 / XE-1AJ Compatible games:
Code:
FM Towns:
After Burner III
Chase HQ
Galaxy Force II
Turbo Outrun
Wing Commander*
Wing Commander 2*
Wing Commander Armada*
Wing Commander Secret Missions*
*Needs confirmation.
X68000:
Afterburner
Dash Yarou
Knight Arms
Metal Sight
Neural Gear
Overtake
Racing Champ
Space Cruiser
Space Harrier (requires patch which was officially distributed with Afterburner)
Star Luster
Super Hang-On
Syvalion
Thunder Blade
PC Engine (requires the XHE-3 adapter):
Afterburner II
Forgotten Worlds
Operation Wolf
Outrun
Thunder Blade
Mega Drive:
After Burner II
Ayrton Senna's Super Monaco GP II
Fastest 1
Galaxy Force II
Musha Aleste: Full Metal Fighter Ellinor (Buggy)
Mega CD:
After Burner III
Night Striker (you must connect it to port 2 and use a regular controller in port 1 to choose the analog mode)
Starblade
32X:
After Burner Complete
Space Harrier