home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Frozen Fish 1: Amiga
/
FrozenFish-Apr94.iso
/
bbs
/
alib
/
d1xx
/
d186
/
qt2.lha
/
QT2
/
qt2.asm
< prev
next >
Wrap
Assembly Source File
|
1989-02-26
|
11KB
|
419 lines
ttl 'QT2 - approximate time display (version 87/10/05)'
sys macro ;Call a system routine.
ifnd _LVO\1
xref _LVO\1
endc
jsr _LVO\1(a6)
endm
code
*
* Equates
*
lf equ $0A ;Line feed
cr equ $0D ;Carriage return
pr_MsgPort equ $5C
pr_CLI equ $AC
CMD_WRITE equ 3 ;Write command
*
* External references (most are taken care of by the SYS macro)
*
xref _AbsExecBase
xref _CreatePort
xref _DeletePort
xdef _SysBase
xdef _DOSBase
*
* Initialization
*
start: move.l sp,savesp ;Save the stack pointer.
clr.l _DOSBase ;Clear library pointers.
clr.l intbase
clr.l trnbase
clr.l voice_port
* Open dos.library
move.l _AbsExecBase,a6 ;Find library
move.l a6,_SysBase
lea dosname,a1 ;'dos.library'
moveq #0,d0 ;Any version
sys OpenLibrary ;Open dos.library.
move.l d0,_DOSBase ;Save it for future reference.
beq quitprg ;Couldn't get pointer.
* Find out whether we were called from a CLI.
suba.l a1,a1
move.l _SysBase,a6
sys FindTask ;Find our task control block.
move.l d0,a4
move.l pr_CLI(a4),prcli ;Save pointer to CLI.
beq.s openwb ;We were called from Workbench.
* Get file handles for stdin and stdout.
move.l _DOSBase,a6 ;Pointer to dos.library
sys Input ;Get file handle for keyboard.
move.l d0,stdin ;Save it here.
beq quitprg ;Couldn't get keyboard handle.
sys Output ;Get file handle for screen.
move.l d0,stdout ;Save it here.
beq quitprg ;Couldn't get screen handle.
bra.s openint
* Special Workbench startup stuff
openwb lea pr_MsgPort(a4),a0
move.l _SysBase,a6
sys WaitPort ;Wait for startup message from Workbench.
lea pr_MsgPort(a4),a0
sys GetMsg ;Get the message.
move.l d0,retmsg ;Save it so we can return it when we're done.
* Open intuition.library
openint move.l _SysBase,a6
lea intname,a1
moveq #0,d0
sys OpenLibrary
move.l d0,intbase
bne.s opened ;We got it opened.
lea interr,a0
bsr pstring ;Indicate open failure.
bra quitprg ;Exit.
opened:
*
* Get the time and convert it to cute notation.
*
* Get the time - put hour in D6 and minute in D7.
move.l _DOSBase,a6
move.l #dtstamp,d1
sys DateStamp ;Get the time.
move.l dtstamp+4,d7 ;Work with the time here.
divu #60,d7 ;Convert to hours and minutes.
moveq #0,d6
move.w d7,d6 ;Work with hours here.
clr.w d7
swap d7 ;Get minutes in low-order word.
lea timemsg,a2 ;A2 loads the final message.
lea its,a0
bsr copy ;"It's "
* Adjust for minutes "to" the next hour if it's after (approximately) half past.
cmpi.w #33,d7 ;33 minutes or more past the hour?
bcs.s adjhr ;No.
addq.l #1,d6 ;It's time "to" the next hour.
adjhr cmpi.w #13,d6 ;Is it in the afternoon?
bcs.s adj12 ;No.
subi.w #12,d6 ;Keep it in the range 1..12
adj12 tst.w d6 ;Is hour zero?
bne.s adj5 ;No.
moveq #12,d6 ;Set hour to 12.
* Look up nearness to a 5-minute interval.
adj5 addq.l #2,d7 ;Adjust for 5-minute rounding
cmpi.w #60,d7
bcs.s near
sub.w #60,d7 ;Adjust for carry into the next hour.
* Express how near we are to the 5-minute interval.
near divu #5,d7 ;Divide adjusted minute by 5.
swap d7 ;Get the remainder
move.w d7,d0
asl.w #2,d0 ;Multiply by 4 for longword displacement
lea nearptr,a0
move.l 0(a0,d0.w),a0 ;Pointer to appropriate "near" phrase
bsr copy ;Copy phrase to string.
* Now put in the appropriate 5-minute phrase itself.
swap d7 ;(minute+2)/5
asl.w #2,d7
lea minptr,a0
move.l 0(a0,d7.w),a0 ;Pointer to appropriate minute phrase
bsr copy
* Say whether it's past the previous hour or approaching the next hour.
tst.b d7 ;Is it around the hour?
beq.s hrname ;Yes - don't say anything here.
lea past,a0 ;Assume it's past the hour
cmpi.w #28,d7 ;Is it approaching the next hour?
bcs.s pastto ;No.
lea to,a0
pastto bsr copy
* Now add the hour name.
hrname subq.l #1,d6 ;Convert 1..12 to 0..11
asl.w #2,d6
lea hrptr,a0
move.l 0(a0,d6.w),a0
bsr copy
* Finish off the string and display it.
tst.w d7 ;Is it around the hour?
bne.s moveper ;No.
lea oclock,a0
bsr copy ;Add " o'clock".
moveper lea period,a0
bsr copy ;Finish off the message.
move.l a2,d0 ;Save ending address.
subq.l #1,d0 ;Back over the terminating null.
lea timemsg,a0
sub.l a0,d0 ;Length of string
move.l d0,timelen
tst.l prcli ;Were we called from a CLI?
beq.s saytime ;No - just say the time.
bsr pstring ;Display the time.
*
* Now say the time (if we can!).
*
saytime
* Translate the string to phonemes.
move.l _SysBase,a6
lea trnname,a1
moveq #0,d0
sys OpenLibrary ;Open translator.library.
move.l d0,trnbase
beq notalk ;The open failed - forget it.
lea timemsg,a0 ;Address of original string
move.l timelen,d0 ;Length of original string
lea tranmsg,a1 ;Address of translated string
moveq #tranmax,d1 ;Maximum length
move.l trnbase,a6
sys Translate ;Translate the string.
* Open a reply port for the narrator.
clr.l -(sp)
clr.l -(sp)
jsr _CreatePort ;voice_port = CreatePort (0L, 0L);
add.l #8,sp
move.l d0,voice_port
move.l d0,mn_ReplyPort
beq notalk ;Couldn't create the port!
* Set up the write channel information.
move.l #audio_chan,ch_masks
move.w #audio_chan_len,nm_masks
clr.b mouths
move.w #CMD_WRITE,io_Command
clr.l io_Offset
move.l #voice_io_len,mn_Length
lea tranmsg,a0
move.l a0,io_Data
tranlen tst.b (a0)+
bne.s tranlen ;Determine length of phoneme string.
suba.l #1,a0
sub.l io_Data,a0
move.l a0,io_Length
* Open the device and say the time.
lea narname,a0
moveq #0,d0
lea voice_io,a1
moveq #0,d1
move.l _SysBase,a6
sys OpenDevice
tst.l d0 ;Were we successful?
bne notalk ;No.
lea voice_io,a1
move.l _SysBase,a6
sys DoIO ;Say the time.
lea voice_io,a1
move.l _SysBase,a6
sys CloseDevice ;Close narrator.device.
bra.s quitprg ;We made it!
* We were unable to talk - display a requester saying so.
notalk suba.l a0,a0
lea notalki,a1
suba.l a2,a2
lea foritxt,a3
moveq #0,d0
moveq #0,d1
move.l #200,d2
moveq #50,d3
move.l intbase,a6
sys AutoRequest ;Display the requester.
*
* End of program, one way or another
*
quitprg move.l savesp,sp ;Restore stack pointer.
move.l voice_port,d0
beq.s clostrn
move.l d0,-(sp)
jsr _DeletePort ;Delete the narrator message port.
add.l #4,sp
clostrn move.l _SysBase,a6
move.l trnbase,d0 ;Close translator.library.
beq.s closint ;It wasn't opened.
move.l d0,a1
sys CloseLibrary
closint move.l intbase,d0 ;Close intuition.library.
beq.s closdos
move.l d0,a1
sys CloseLibrary
closdos move.l _DOSBase,d0 ;Close dos.library.
beq.s endwb
move.l d0,a1
sys CloseLibrary
endwb tst.l prcli ;Were we called from a CLI?
bne.s exit0 ;Yes.
move.l _SysBase,a6
sys Forbid ;Don't let Workbench UnLoadSeg() us.
move.l retmsg,a1
sys ReplyMsg ;Return the startup message to Workbench.
exit0 moveq #0,d0 ;Return with no error.
rts ;All done
*
* Copy the null-terminated string pointed to by A0 to (A2).
* On exit, A2 points to the last byte copied (i.e. the null).
*
copy move.b (a0)+,(a2)+ ;Move one character.
bne.s copy ;Get the next character.
suba.l #1,a2 ;Back over the null.
rts
*
* Display the null-terminated string pointed to by A0.
*
pstring movem.l d2-d3/a6,-(sp)
move.l a0,d2 ;AmigaDOS wants the address here.
pstrl tst.b (a0)+ ;Scan for end of string.
bne.s pstrl
move.l a0,d3 ;AmigaDOS wants the length here.
sub.l d2,d3 ;Length plus one
subq.l #1,d3 ;Reduce to proper length.
move.l stdout,d1
move.l _DOSBase,a6
sys Write ;Write the string.
movem.l (sp)+,d2-d3/a6
rts
page
*************************************************************************
* *
* Constants *
* *
*************************************************************************
section Constants,data
dosname dc.b 'dos.library',0
intname dc.b 'intuition.library',0
trnname dc.b 'translator.library',0
interr dc.b 'Unable to open intuition.library',cr,lf,0
narname dc.b 'narrator.device',0
notalkm dc.b 'I can''t talk!',0
fortext dc.b 'Forget it',0
its dc.b 'It''s ',0
nearptr dc.l almost,nearly,null,justaft,justpas
almost dc.b 'almost ',0
nearly dc.b 'nearly ',0
null dc.l 0
justaft dc.b 'just after ',0
justpas dc.b 'just past ',0
minptr dc.l null,five,ten,quarter,twenty,twenfiv,half
dc.l twenfiv,twenty,quarter,ten,five
quarter dc.b 'a quarter',0
half dc.b 'half',0
hrptr dc.l one,two,three,four,five,six,seven,eight,nine,ten,eleven,twelve
one dc.b 'one',0
two dc.b 'two',0
three dc.b 'three',0
four dc.b 'four',0
five dc.b 'five',0
six dc.b 'six',0
seven dc.b 'seven',0
eight dc.b 'eight',0
nine dc.b 'nine',0
ten dc.b 'ten',0
eleven dc.b 'eleven',0
twelve dc.b 'twelve',0
twenty dc.b 'twenty',0
twenfiv dc.b 'twenty-five',0
to dc.b ' to ',0
past dc.b ' past ',0
oclock dc.b ' o''clock',0
period dc.b '.',cr,lf,0
audio_chan dc.b 3,5,10,12 ;Which audio channels to use
audio_chan_len equ *-audio_chan
* IntuiText structures for "can't-talk" requester
cnop 0,4
notalki ;BodyText
dc.b 0,1,0,0
dc.w 10,5
dc.l 0,notalkm,0
foritxt ;NegativeText
dc.b 0,1,0,0
dc.w 4,3
dc.l 0,fortext,0
page
*************************************************************************
* *
* Storage areas *
* *
*************************************************************************
section Storage,bss
savesp ds.l 1 ;Stack pointer save area
retmsg ds.l 1 ;Pointer to Workbench startup message
_SysBase ds.l 1 ;Copy of _AbsExecBase
_DOSBase ds.l 1 ;Pointer to dos.library
intbase ds.l 1 ;Pointer to intuition.library
trnbase ds.l 1 ;Pointer to translator.library
prcli ds.l 1 ;Pointer to CLI or zero
stdin ds.l 1 ;stdin file handle
stdout ds.l 1 ;stdout file handle
dtstamp ds.l 3 ;Date stamp (days, minutes, ticks)
timemsg ds.b 41 ;Time message is built here.
timelen ds.l 1 ;Actual length of time message
tranmsg ds.b 80 ;"timemsg" translated to phonemes
tranmax equ *-tranmsg
voice_port ds.l 1 ;Pointer to message port for narrator.device
*
* Narrator write request
*
voice_io ;struct narrator_rb
message ;struct IOStdReq
io_Message ;struct Message
mn_Node ;struct Node
ln_Succ ds.l 1 ;Pointer to successor Node
ln_Pred ds.l 1 ;Pointer to predecessor Node
ln_Type ds.b 1
ln_Pri ds.b 1
ln_Name ds.l 1 ;Pointer
; End of struct Node
mn_ReplyPort ds.l 1 ;Pointer to MsgPort (message reply port)
mn_Length ds.w 1 ;Message length in bytes
; End of struct Message
io_Device ds.l 1 ;Pointer to device node
io_Unit ds.l 1 ;Pointer to Unit (driver private)
io_Command ds.w 1 ;Device command
io_Flags ds.b 1
io_Error ds.b 1 ;Error or warning number
; End of struct IOReq - IOStdReq continues...
io_Actual ds.l 1 ;Actual number of bytes transferred
io_Length ds.l 1 ;Requested number of bytes transferred
io_Data ds.l 1 ;Points to data area.
io_Offset ds.l 1 ;Offset for block-structured devices
; End of struct IOStdReq
rate ds.w 1 ;Speaking rate (words per minute)
pitch ds.w 1 ;Baseline pitch in Hertz
mode ds.w 1 ;Pitch mode
sex ds.w 1 ;Sex of voice
ch_masks ds.l 1 ;Pointer to audio allocation maps
nm_masks ds.w 1 ;Number of audio allocation maps
volume ds.w 1 ;Volume: 0 (off) thru 64 (maximum)
sampfreq ds.w 1 ;Audio sampling frequency
mouths ds.b 1 ;If non-zero, generate mouths.
chanmask ds.b 1 ;Which channel mask used (internal)
numchan ds.b 1 ;Number of channel masks used (internal)
ds.b 1 ;For alignment
voice_io_len equ *-voice_io ; End of struct narrator_rb
end