home *** CD-ROM | disk | FTP | other *** search
- * Sprite Clock
- *
- * This is a very simple clock that uses a sprite as it's display medium.
- * It displays the time every minute for a couple seconds and then the sprite
- * disappears. The time is displayed in 12-hr. format; you'll have to figure
- * out if it is AM or PM yourself.
- * It is useful if you are working on different screens alot since a sprite
- * will appear in front of any screen.
- * I had to design the numbers myself and I used alot of tricks to compress
- * the space their data would have taken so that the clock will remain small.
- * I would think that there is some way to take advantage of the fonts already
- * in the system but I did not know enough about the form of the font in
- * memory and how to access that data so that it could be used.
- * Alot of different techniques are used in order to load the numerals into
- * memory and I would think they would prove educational to someone.
-
- * At this time this clock can not be terminated once it is started.
- * I don't mind this since it takes up very little memory. This program
- * could be given another port and a close message could be sent to it by
- * another program or by something like the workbench menus if they where
- * properly altered.
-
- * Code size: 820 bytes
- * minumum stack: 1600 bytes
- * Running size: 6312 bytes
-
- * I do not think it will work from the workbench in it's current version.
-
- * Darrel Schneider
- ************************************************************************
-
- NOPAGE
- NOLIST
- LLEN 132
-
- ; INCLUDE "exec/types.i"
- ; INCLUDE "exec/ables.i"
- ; INCLUDE "exec/memory.i"
- ; INCLUDE "devices/timer.i"
-
- * the following equates take the place of the info in the above files
-
- MP_SIZE: EQU $22
- MP_SIGBIT: EQU $F
- MEMF_CLEAR: EQU $10000
- MEMF_PUBLIC: EQU $1
- MEMF_CHIP: EQU $2
- NT_MSGPORT: EQU $4
- NT_MESSAGE: EQU $5
- IOTV_SIZE: EQU $28
- LN_TYPE: EQU $8
- LN_NAME: EQU $A
- IO_DEVICE: EQU $14
- IO_UNIT: EQU $18
- IO_COMMAND: EQU $1C
- IO_SIZE: EQU $20
- MN_REPLYPORT: EQU $E
- TR_ADDREQUEST: EQU $9
- TR_GETSYSTIME: EQU $A
- UNIT_VBLANK: EQU $1
- TV_SECS: EQU $0
- TV_MICRO: EQU $4
-
- XREF _AbsExecBase
-
- XREF _LVOOpenLibrary
- XREF _LVOCloseLibrary
-
- XREF _LVOAllocMem
- XREF _LVOFreeMem
-
- XREF _LVOAllocSignal
- XREF _LVOFreeSignal
-
- XREF _LVOAddPort
- XREF _LVORemPort
-
- XREF _LVOOpenDevice
- XREF _LVOCloseDevice
-
- XREF _LVODoIO
- XREF _LVOSendIO
- XREF _LVOWaitIO
-
- XREF _LVOFindTask
-
- XREF _LVOGetSprite
- XREF _LVOChangeSprite
- XREF _LVOMoveSprite
- XREF _LVOFreeSprite
-
- LIST
- Temp: EQUR d2
- LoopCount: EQUR d2
- Secs: EQUR d3
- Micros: EQUR d4
- AndMask: EQUR d5
- Timer_Port: EQUR d6
- GraphicsBase: EQUR d7
-
- BufferPTR: EQUR a2
- SimpleSpritePTR: EQUR a3
- NewDataPTR: EQUR a4
- Time_ReqPTR: EQUR a5
-
- ********** open libraries ***********
-
- movea.l _AbsExecBase,a6
- lea GraphicsName(pc),a1
- moveq.l #0,d0
- jsr _LVOOpenLibrary(a6)
- tst.l d0
- bne.s NOAbortOpenLibrary ;V
- rts ;quit
- NOAbortOpenLibrary:
- move.l d0,GraphicsBase
-
- ********** create timer port **********
-
- ;get a signal bit
- moveq.l #-1,d0
- jsr _LVOAllocSignal(a6)
- move.l d0,d2
- bmi.l AbortCreateTimer1 ; if -1 AllocSignal failed so abort
-
- ; alloc port structure
- moveq.l #MP_SIZE,d0
- move.l #(MEMF_CLEAR!MEMF_PUBLIC),d1
- jsr _LVOAllocMem(a6)
- move.l d0,Timer_Port
- bne.s skipAbortCode ;V it was allocated so skip the abort code
- ; AllocMem failed so clean up and then abort
- move.l d2,d0
- jsr _LVOFreeSignal(a6)
- bra.l AbortCreateTimer2 ; if 0 AllocMem failed so abort
-
- skipAbortCode:
- ; fill port fields
- move.l Timer_Port,a2
- addq.l #8,a2 ; a2 = &LN_TYPE
- move.w #((NT_MSGPORT<<8)+Priority),(a2)+
- ; the last instruction does the next two
- ; move.b #NT_MSGPORT,(a2)+ ; LN_TYPE
- ; move.b #Priority,(a2)+ ; LN_PRI
- lea TimerPortName(pc),a1
- move.l a1,(a2)+ ; LN_NAME gets &TimerPortName
- ; this instruction is done by the next one since it is a move.w
- ; clr.b (a2)+ ; #PA_SIGNAL -> MP_FLAGS
- move.w d2,(a2)+ ; MP_SIGBIT
- moveq.l #0,d0
- movea.l d0,a1
- jsr _LVOFindTask(a6)
- move.l d0,(a2) ; MP_SIGTASK
- ; add the port
- movea.l Timer_Port,a1
- jsr _LVOAddPort(a6)
-
- bra.s SkipAbortSection ;V
-
- *******************************************************************************
- ************************** TERMINATION SECTION *****************************
-
- AbortNewDataAlloc:
- moveq.l #0,d0
- move.w 10(SimpleSpritePTR),d0
- exg a6,GraphicsBase
- jsr _LVOFreeSprite(a6)
- exg a6,GraphicsBase
- AbortGetSprite:
- moveq.l #IOTV_SIZE,d4
- adda.l d4,Time_ReqPTR
- adda.l d4,Time_ReqPTR
- moveq.l #1,d3
- bra.s BEGINCloseDeviceLOOP ;V
- AbortOpenDevice:
- subq.l #1,d3
- beq.s SKIPCloseDeviceLOOP ;V
- moveq.l #0,d3
- BEGINCloseDeviceLOOP:
- ; close timer device
- suba.l d4,Time_ReqPTR
- lea (Time_ReqPTR),a1
- jsr _LVOCloseDevice(a6)
- dbra d3,BEGINCloseDeviceLOOP ;^
-
- SKIPCloseDeviceLOOP:
- ; deallocate Time_Req structure
- moveq.l #-1,d3
- movea.l Time_ReqPTR,a1
- moveq.l #1,d0
- DeallocateLOOP:
- move.b d3,LN_TYPE(Time_ReqPTR)
- move.l d3,IO_DEVICE(Time_ReqPTR)
- move.l d3,IO_UNIT(Time_ReqPTR)
- adda.l d4,Time_ReqPTR
- dbra d0,DeallocateLOOP
- moveq.l #IOTV_SIZE*2,d0
- jsr _LVOFreeMem(a6)
-
- AbortTime_ReqAlloc:
- ; close timer port
- movea.l Timer_Port,a1
- jsr _LVORemPort(a6)
- movea.l Timer_Port,a2
- ; d3 = -1
- move.b d3,LN_NAME(a2)
- move.l d3,(a2) ; LH_HEAD
- move.l MP_SIGBIT(a2),d0
- jsr _LVOFreeSignal(a6)
- movea.l Timer_Port,a1
- moveq.l #MP_SIZE,d0
- jsr _LVOFreeMem(a6)
-
- AbortCreateTimer2:
- AbortCreateTimer1:
- move.l GraphicsBase,a1
- jsr _LVOCloseLibrary(a6)
-
- moveq.l #0,d0
- rts
-
- ********************* END OF TERMINATION SECTION ***************************
- ****************************************************************************
-
- SkipAbortSection:
-
- ********** initialize timerequest struct ***********
-
- ;alloc timerequest structure
- moveq.l #IOTV_SIZE*2,d0
- move.l #(MEMF_CLEAR!MEMF_PUBLIC),d1
- jsr _LVOAllocMem(a6)
- tst.l d0
- beq.s AbortTime_ReqAlloc
- movea.l d0,Time_ReqPTR
-
- move.w #((NT_MESSAGE<<8)+Priority),LN_TYPE(Time_ReqPTR)
- ; The previous instruction actually does the next two.
- ; move.b #NT_MESSAGE,LN_TYPE(Time_ReqPTR)
- ; move.b #Priority,LN_PRI(Time_ReqPTR)
- move.l Timer_Port,MN_REPLYPORT(Time_ReqPTR)
- ; cleared in the AllocMem call
- ; clr.w IO_FLAGS(Time_ReqPTR) ; this also zeros IO_ERROR
- move.w #TR_ADDREQUEST,IO_COMMAND(Time_ReqPTR)
-
- moveq.l #IOTV_SIZE,d0
- move.w #((NT_MESSAGE<<8)+Priority),LN_TYPE(Time_ReqPTR,d0.w)
- move.w #TR_GETSYSTIME,IO_COMMAND(Time_ReqPTR,d0.w)
-
-
- ********** open vblank timer device **************
-
- moveq.l #1,d3
- moveq.l #IOTV_SIZE,d4
- OpenDeviceLOOP:
- lea TimerName(pc),a0
- lea (Time_ReqPTR),a1
- moveq.l #UNIT_VBLANK,d0
- moveq.l #0,d1
- jsr _LVOOpenDevice(a6)
- tst.l d0
- bne.l AbortOpenDevice
- adda.l d4,Time_ReqPTR
- dbra d3,OpenDeviceLOOP
- sub.l d4,Time_ReqPTR
- sub.l d4,Time_ReqPTR
-
- ********** initialize the Sprite *******************
-
- lea SimpleSprite(pc),SimpleSpritePTR
- move.l SimpleSpritePTR,a0
- moveq.l #-1,d0
- exg a6,GraphicsBase
- jsr _LVOGetSprite(a6)
- exg a6,GraphicsBase
- tst.l d0
- bmi AbortGetSprite
-
- move.w #43,4(SimpleSpritePTR)
- clr.l 6(SimpleSpritePTR)
-
- ********** initialize newData structure used by the Sprite **********
-
- move.w #newDataSIZE,d0
- move.l #(MEMF_CLEAR!MEMF_CHIP),d1
- jsr _LVOAllocMem(a6)
- tst.l d0
- beq AbortNewDataAlloc
- movea.l d0,NewDataPTR
-
- moveq.l #(newDataSIZE/4)-3,d0
- lea 4(NewDataPTR),a0
- move.l #term,d1
- BEGINnewDataLOOP:
- move.l d1,(a0)+
- dbra d0,BEGINnewDataLOOP ;^
- move.w #colon,88(NewDataPTR)
-
- ********** initialize program register variables *****************
-
- lea buffer(pc),BufferPTR
- moveq.l #AndMaskVALUE,AndMask
-
- ********************* main loop *******************
-
- bsr.s GetSecsTillNextMin
- cmpi.w #5,Secs
- bpl.s DisplayTime ;V
- bra.s WaitTillNextMin ;V
- RESTART:
- bsr.s GetSecsTillNextMin
- DisplayTime:
- bsr.s LoadBuffer
- bsr.s GetSecsTillNextMin ;only needs to get Secs & Micros
- WaitTillNextMin:
- move.w Secs,2+IO_SIZE+TV_SECS(Time_ReqPTR)
- move.l Micros,IO_SIZE+TV_MICRO(Time_ReqPTR)
- movea.l Time_ReqPTR,a1
- jsr _LVODoIO(a6)
- bra RESTART ;^
-
- ***************************** SUBROUTINES **********************************
- GetSecsTillNextMin:
- moveq.l #SEC_PER_MIN-1,Secs
- move.l #MICRO_PER_SEC-1,Micros
- ; get the current time
- lea IOTV_SIZE(Time_ReqPTR),a1
- jsr _LVODoIO(a6)
-
- ; calculate # of Secs. till next minute and put it in d0
- move.l IOTV_SIZE+IO_SIZE+TV_SECS(Time_ReqPTR),d0
- sub.l IOTV_SIZE+IO_SIZE+TV_MICRO(Time_ReqPTR),micros
- ; moveq.l #0,Temp ; clear to zero meaning AM
- divu #SEC_PER_HALF,d0
- ; lsr.b #1,d0 ; test lsbit by shifting it into C bit
- ; bcc.s AM ;V
- ; moveq.l #12,Temp ; make it 12 if PM
- ; AM:
- swap d0 ; d0 = # of seconds in the half day
- exg d0,d1
- moveq.l #0,d0
- move.w d1,d0
- divu #SEC_PER_MIN,d0
- ; swap Temp
- move.w d0,Temp ; save the minutes*hrs. in half day
- swap d0
- sub.w d0,Secs
-
- rts
-
- **********************************************
- LoadBuffer:
- ; BufferPTR = &buffer[0]
- clr.l (BufferPTR)
- ; load buffer with the current time
- moveq.l #0,d0
- move.w Temp,d0 ; d0 has minutes*hrs. in half day
- ; clr.w Temp
- ; swap Temp
- divu #MIN_PER_HOUR,d0
- moveq.l #0,d1
- add.w d0,d1 ; prepare # of hours in half day
-
- divu #10,d1
- tst.l d1
- bne.s WasNot12 ;V
- move.w #$0102,(bufferPTR)+
- bra.s Load2and3 ;V
- WasNot12:
- tst.w d1
- bne.s WasNotZero ;V
- BlankOffset: EQU $a
- move.b #BlankOffset,d1
- WasNotZero:
- move.b d1,(BufferPTR)+ ; buffer[0]
- swap d1
- move.b d1,(BufferPTR)+ ; buffer[1]
-
- Load2and3:
- swap d0
- ext.l d0
- divu #10,d0
- move.b d0,(BufferPTR)+ ; buffer[2]
- swap d0
- move.b d0,(BufferPTR)+ ; buffer[3]
-
- ; BufferPTR= &buffer[3]+1
-
- ; Print Sprite
- lea num4(NewDataPTR),a1
- bsr.s LoadSpriteNumber
- ; BufferPTR= &buffer[3]
-
- lea num3(NewDataPTR),a1
- bsr.s LoadSpriteNumber
- ; BufferPTR= &buffer[2]
-
- lea num2(NewDataPTR),a1
- bsr.s LoadSpriteNumber
- ; BufferPTR= &buffer[1]
-
- lea num1(NewDataPTR),a1
- bsr.s LoadSpriteNumber
- ; BufferPTR= &buffer[0]
-
- moveq.l #0,d3
-
- move.l d3,a0
- move.l SimpleSpritePTR,a1
- move.l a2,-(sp)
- movea.l NewDataPTR,a2
- exg a6,GraphicsBase
- jsr _LVOChangeSprite(a6)
-
- move.l d3,a0
- move.l SimpleSpritePTR,a1
- move.l #300,d0
- moveq.l #70,d1
- jsr _LVOMoveSprite(a6)
-
- move.w #3,2+IO_SIZE+TV_SECS(Time_ReqPTR) ; wait 3 Secs
- ; clr.l IO_SIZE+TV_MICRO(Time_ReqPTR)
- exg a6,GraphicsBase
- lea (Time_ReqPTR),a1
- jsr _LVODoIO(a6)
- exg a6,GraphicsBase
-
- moveq.l #0,d0
- move.l #244,d1
- move.l d0,a0
- move.l SimpleSpritePTR,a1
- jsr _LVOMoveSprite(a6)
- exg a6,GraphicsBase
-
- move.l (sp)+,a2
-
- rts
-
- ******************** LoadSpriteNumber ************************
- ; loads the image of the number in -(BufferPTR)
- ; into the memory whose first long has the address in A1.
-
- LoadSpriteNumber:
- moveq.l #0,d0
- move.b -(BufferPTR),d0
- asl.b #2,d0 ; multiply by 4
- move.l recipeTABLE(pc,d0.w),d1
-
- moveq.l #7,LoopCount
- BEGINdecodeRecipeLOOP:
- move.l d1,d0
- and.w AndMask,d0
- move.b imageTABLE(pc,d0.w),d0
- lsl.w #4,d0
- move.w d0,(a1)+
- addq.l #2,a1
- lsr.l #4,d1 ; get next 4-bit incoded image
- dbra LoopCount,BEGINdecodeRecipeLOOP ;^
-
- rts
-
- imageTABLE:
- DC.B twoDots
- DC.B Dot1
- DC.B Dot2
- DC.B blank
- DC.B Dot4
- DC.B Dot5
- DC.B Dot6
- DC.B Dot7
- DC.B Dot8
- DC.B bar
- DC.B lBar
- DC.B rBar
- DC.B sBar
- DC.B triple
- DC.B fours2Dot
- DC.B onesBigDot
-
- recipeTABLE: CNOP 0,2
- zero: DC.L $c000000c
- one: DC.L $d44444f4
- two: DC.L $b111c88c
- three: DC.L $a888c88a
- four: DC.L $7779eee7
- five: DC.L $c088a119
- six: DC.L $c00a112f
- seven: DC.L $5556788b
- eight: DC.L $c000c00c
- nine: DC.L $6788b00c
- space: DC.L $33333333
-
-
- ***********************************************************************
- * SECTION "initialized data",DATA
-
- twoDots: EQU $81
- Dot1: EQU $80
- Dot2: EQU $40
- blank: EQU $00
- Dot4: EQU $10
- Dot5: EQU $08
- Dot6: EQU $04
- Dot7: EQU $02
- Dot8: EQU $01
- bar: EQU $ff
- lBar: EQU $fe
- rBar: EQU $7f
- sBar: EQU $7e
- triple: EQU $38
- fours2Dot: EQU $82
- onesBigDot: EQU $30
-
- colon: EQU $0440
- term: EQU $7ffe
- line: EQU $00
-
-
- AndMaskVALUE: EQU $f
-
- TimerPortName: CNOP 0,2
- DC.B 'timer',0
- Priority: EQU 0
- TimerName: CNOP 0,2
- DC.B 'timer.device',0
- GraphicsName: CNOP 0,2
- DC.B 'graphics.library',0
-
- MICRO_PER_SEC: EQU 1000000
- SEC_PER_MIN: EQU 60
- MIN_PER_HOUR: EQU 60
- SEC_PER_HOUR: EQU (60*60)
- SEC_PER_HALF: EQU (60*60*12)
- SEC_PER_DAY: EQU (60*60*24)
- HOUR_PER_DAY: EQU 24
-
- newDataSIZE: EQU 196-16
- ; newData offsets
- num1: EQU 12
- num2: EQU 52
- num3: EQU 96
- num4: EQU 136
-
- * SECTION "uninitialized data",BSS
- buffer: CNOP 0,2
- DS.B 4
- SimpleSprite: CNOP 0,2
- DS.W 6
- END
-