;****** Auto-Revision Header (do not edit) *******************************
;*
;* © This is Freeware (All rights are reserved by Peter Simons!)
;*
;* Filename         : CpuClr.asm
;* Created on       : 23-Jul-92
;* Created by       : Oliver Wagner & Peter Simons
;* Current revision : V2.000
;*
;*
;* Purpose: This program replaces the system-routine BltClear() with a
;*          highly optimized 68020/30/40 routine.
;*
;*
;* V2.000 : Final version! (??)        released: Peter Simons (24-Jul-02)
;*
;* V1.042 : fixed bug in CPU-recognition
;*
;* V1.040 : Changed addressing mode in clear-loop! Again saved a few
;*          bytes and cyles...
;*
;* V1.034 : I corrected a few typing-errors in the sourcecode
;*
;* V1.033 : I called SetFunction() with wrong parameters, which caused
;*          the machine to crash immediately. (I'll never find out why it
;*          worked on my Amiga all the time?? Don't ask! It's magic!)
;*
;* V1.032 : Added secure/unsecure switch
;*
;* V1.031 : released: Peter Simons (24-Jul-02)
;*
;* V1.030 : saved again 4 bytes by changing the addressing mode in the
;*          clear loop
;*
;* V1.028 : NewBltClr won't crash the machine any longer if a blocksize
;*          of ZERO is specified
;*
;* V1.027 : NewBltClr has only one exit-point now --> saves some bytes
;*
;* V1.026 : saved one swap-command in long-align-routine
;*
;* V1.025 : fixed minor bug: SIZE % 4 = 0 was NOT recognized by NewBltClr
;*
;* V1.020 : deleted opcodes in size-calculation: clearing the upper word
;*          was a waste, because MULU works only on WORD-size
;*
;* V1.011 : optimized output-routines and saved some bytes
;*
;* V1.010 : the way how the patch is installed, has been completely re-
;*          written and is shorter and, in my eyes, system-friendlier...
;*
;* V1.006 : program won't crash, if no standard-output is available!
;*          (for example, if started out of DME...)
;*
;* V1.005 : program checks for at least OS 2.04 and 68020 or higher
;*
;* V1.004 : changed program-output and added OS 2.0-version-string
;*
;* V1.003 : minor changes to the source-code
;*          revision header added
;*          changed to Macro68k-Assembler
;*
;* V1.002 : merged hunks --> program is position independent
;*
;* V1.001 : I continue development: Peter Simons (23-Jul-92)
;*
;* V1.000 : written by Oliver Wagner
;*
;* V0.000 : --- Initial release ---
;*
;*************************************************************************
;
;

;***************************************************************************
;*                                                                         *
;* SEKTION: Labels, Macros, Switches, Structures                           *
;*                                                                         *
;***************************************************************************

;-------------------------------------- Switches -----------
                MC68000
                EXEOBJ
                OBJFILE "ram:CPUClr"
                NEWSYNTAX

SECURECODE      set     1       ; test everything that could possibly
                                ; crash the machine
;-------------------------------------- Exec ---------------
eb_AttnFlags    equ     $0128
lib_Version     equ     $0014

MEMF_PUBLIC     equ     1<<0
AF_68020        equ     1

;-------------------------------------- Labels -------------
                MACLIB  "DATAS:Offsets.preass"
KICKVERSION     equ     37

_DOSBase        equr    A5
_GfxBase        equr    A4
_NewBltClr      equr    A3
_OutputHandle   equr    D7

;-------------------------------------- Macros -------------
REVISION        MACRO
                dc.b "2.000"
                ENDM
REVDATE         MACRO
                dc.b "24-Jul-02"
                ENDM


;***************************************************************************
;*                                                                         *
;* SEKTION: Program                                                        *
;*                                                                         *
;***************************************************************************

START:          move.l  ($4).W,a6
        IFNE SECURECODE
                cmp.w   #KICKVERSION,(lib_Version,a6)   ; Kickstart 2.04+ ?
                bmi     .ErrorExit
                btst    #AF_68020,(eb_AttnFlags+1,a6)     ; 68020+ ?
                beq     .ErrorExit
        ENDC
                lea     (dosname,PC),a1
                jsr     (_LVOOldOpenLibrary,a6)         ; open Dos-Library
        IFNE SECURECODE
                tst.l   d0
                beq     .ErrorExit
        ENDC
                move.l  d0,_DOSBase

                lea     (gfxname,PC),a1
                jsr     (_LVOOldOpenLibrary,a6)         ; open Graphics-Lib
        IFNE SECURECODE
                tst.l   d0
                beq     .CloseDosLib
        ENDC
                move.l  d0,_GfxBase

                move.l  _DOSBase,a6
                jsr     (_LVOOutput,a6)                 ; get standard-
                move.l  d0,_OutputHandle                ; outputhandle

                move.l  _OutputHandle,d1
        IFNE SECURECODE
                beq.s   .SkipWrite
        ENDC
                lea     (Header,PC),a0                  ; write standard-
                move.l  a0,d2                           ; header
                moveq   #Header_len,d3
                jsr     (_LVOWrite,a6)

.SkipWrite      move.l  (_LVOBltClear+2,_GfxBase),_NewBltClr ; is the patch
                cmp.l   #'FAST',(new_ID,_NewBltClr)     ; already installed?
                beq.s   .RemovePatch                    ; Yep->remove

;-------------------------------------- install patch ------

                moveq   #NewBltClr_len,d0
                moveq   #MEMF_PUBLIC,d1
                move.l  ($4).W,a6
                jsr     (_LVOAllocVec,a6)
        IFNE SECURECODE
                tst.l   d0
                beq.s   .CloseGfxLib                    ; Can't allocate
        ENDC
                move.l  d0,_NewBltClr                   ; memory

                lea     (NewBltClr,PC),a0
                move.l  _NewBltClr,a1                   ; copy patch into
                moveq   #NewBltClr_len,d0               ; reserved buffer
                jsr     (_LVOCopyMem,a6)

                move.l  _GfxBase,a1
                move.w  #_LVOBltClear,a0                ; patch OS-function
                move.l  _NewBltClr,d0
                jsr     (_LVOSetFunction,a6)
                move.l  d0,(new_OldBltClr,_NewBltClr)   ; save old vector

                lea     (Install,PC),a0                 ; give feedback :-)
                moveq   #Install_len,d3
                bra.s   .exit

;-------------------------------------- remove patch -------
.RemovePatch    move.l  _GfxBase,a1
                move.w  #_LVOBltClear,a0
                move.l  (new_OldBltClr,_NewBltClr),d0
                move.l  ($4).W,a6
                jsr     (_LVOSetFunction,a6)            ; replace old
                move.l  d0,a1                           ; function and
                jsr     (_LVOFreeVec,a6)                ; release memory

                move.l  _DOSBase,a6
                lea     (Remove,PC),a0
                moveq   #Remove_len,d3

;-------------------------------------- exit gracefully ----

.exit           move.l  _OutputHandle,d1
        IFNE SECURECODE
                beq.s   .CloseGfxLib
        ENDC
                move.l  a0,d2
                move.l  _DOSBase,a6
                jsr     (_LVOWrite,a6)

                move.l  _OutputHandle,d1
                lea     (Returns,PC),a0
                move.l  a0,d2
                moveq   #Returns_len,d3
                jsr     (_LVOWrite,a6)

.CloseGfxLib    move.l  _GfxBase,a1
                move.l  ($4).W,a6                       ; close resources
                jsr     (_LVOCloseLibrary,a6)           ; and leave

.CloseDosLib    move.l  _DOSBase,a1
                jsr     (_LVOCloseLibrary,a6)

.ErrorExit      moveq   #0,d0
                rts


;***************************************************************************
;*                                                                         *
;* SEKTION: new BltClear()-Routine                                         *
;*                                                                         *
;***************************************************************************
NewBltClr:                      ; A1=&memBlock
                                ; D0=bytecount
                                ; D1=flags
                move.l  d2,a0                   ; save register
                tst.l   d0                      ; bytecount > 0 ?
                beq.s   .finished               ; Nope -> Exit!
                btst    #1,d1                   ; bytes per row?
                beq.s   .bytesize               ; Nope -> length is alright
                move.l  d0,d2                   ; Yep  -> calc size of
                swap    d2                      ;         memBlock
                mulu    d2,d0
.bytesize       moveq   #0,d2                   ; clear memory or fill with
                btst    #2,d1                   ; pattern??
                beq.s   .dataok
                swap    d1                      ; --> fill with pattern
                move.w  d1,d2
.dataok         btst    #1,d0                   ; --> clear
                beq.s   .LongAlign
                subq.l  #2,d0
.loop1          move.w  d2,(a1)+
                subq.l  #2,d0
                bcc.s   .loop1
.finished       move.l  a0,d2
                rts

.LongAlign      move.w  d2,d1                   ; more efficient routine
                swap    d2                      ; if size of mem-block is:
                move.w  d1,d2                   ; SIZE % 4 = 0
                subq.l  #4,d0
.loop2          move.l  d2,(a1)+
                subq.l  #4,d0
                bcc.s   .loop2
                bra.s   .finished

                cnop    0,4
new_ID          equ     (*-NewBltClr)           ; Offsets for routine-ID and
.ID             dc.l    "FAST"                  ; buffer for OldBltClr
new_OldBltClr   equ     (*-NewBltClr)
.OldBltClr      dc.l    0

NewBltClr_len   equ     (*-NewBltClr)           ; length of routine

;***************************************************************************
;*                                                                         *
;* SEKTION: Daten, Zeiger                                                  *
;*                                                                         *
;***************************************************************************

gfxname         dc.b    "graphics.library",0
dosname         dc.b    "dos.library",0
        IFNE SECURECODE
Header          dc.b    $9B,"1;33",$6D
                dc.b    "$VER: CPUClr "
                REVISION
                dc.b    " ("
                REVDATE
                dc.b    ")"
                dc.b    $9B,$6D
                dc.b    " coding by Peter Simons",$0A
Header_len      equ     (*-Header)
        ELSE
                dc.b    "$VER: "
Header          dc.b    "CPUClr "
                REVISION
                dc.b    ": "
Header_len      equ     (*-Header)
        ENDC

Install         dc.b    "Installed"
Install_len     equ     (*-Install)
Remove          dc.b    "Removed"
Remove_len      equ     (*-Remove)
Returns         dc.b    "...",$0A,$0A
Returns_len     equ     (*-Returns)

                END
