****************************
*   modified STARTUP.ASM   *
* original by Daniel Wolf  *
*     COPYRIGHT 1987       *
*   BY COMPUTE! BOOKS      *
*       06/10/87           *
****************************

; Error Codes

CantInitSystem  EQU  20
CantOpenWindow  EQU  21
CantOpenScreen  EQU  22
CantAllocMem    EQU  23
CantOpenDevice  EQU  24

;*** System Startup Code ***

Start:

   move.l     SP,StackPTR           ; save stack pointer
   move.l     a0,Command            ; save address of command tail
   move.l     d0,CmdLen             ; save length of command tail
   suba.l     a1,a1                 ; Clear a1
   SysCall    FindTask              ; Find address of task's task struct
   move.l     d0,TaskPTR

NowStartup

   move.l     #1,EndFromWB          ; Assume its from WB
   move.l     d0,a2                 ; a2 contains the Task Struct address
   tst.l      proc_CLI(a2)          ; IS this a CLI process?
   beq.s      From_WB               ; No, its from WB

From_CLI                            ; Do this if from CLI

   move.l     #0,EndFromWB
   move.l     #1,EndFromCLI
   move.l     Command,a0            ; retrieve command address
   move.l     CmdLen,d0             ; and length
   clr.b      -1(a0,d0.w)           ; clear a byte at end of command tail
   bsr        _OpenDos              ; open the Dos.library, we need it
   DosCall    Input
   move.l     d0,StdIn              ; set current CLI window as input file
   DosCall    Output
   move.l     d0,StdOut             ; and as output
   move.l     d0,StdErr             ; and as error file
   bra        NowDoMain             ; open libs and run _main

From_WB                             ; do this if from WB

   bsr        _OpenDos
   lea        proc_MsgPort(a2),a0   ; wait for WB message
   SysCall    WaitPort
   lea        proc_MsgPort(a2),a0
   SysCall    GetMsg
   move.l     d0,WBMsg              ; save pointer to this message

   IFD WBC                          ; did we want a console?
DefaultConsole

   move.l     #NewConsole,d1
   move.l     #MODE_NewFile,d2
   DosCall    Open
   move.l     d0,StdIn
   move.l     d0,StdOut
   move.l     d0,StdErr
   beq        _StartError           ; give up if console didn't make it!

SetConTask                          ; we have a BCPL PTR (sigh)

   lsl.l      #2,d0                 ; convert to an address
   move.l     d0,a0                 ; and stuff it in a0 as File Handle
   move.l     TaskPTR,a2            ; and fill in task struct with
   move.l     fh_Type(a0),proc_ConsoleTask(a2)
   ENDC                             ; info about the console


*******   Now open libs and start _Main  *******

NowDoMain
   bsr        _OpenLibs
   bsr        _Main
   tst.l      EndFromWB             ; if from WB, must close Console!
   beq        _Error
   move.l     StdOut,d1             ; if it wasn't opened...
   beq        _Error                ; SKIP IT!
   DosCall    Close

;*** Now clean up and exit to system ***

_Error                              ; here is where we clean up and exit
   move.l     d0,-(SP)              ; hide d0 on the stack
   tst.l      WBMsg                 ; was there a WBmsg?
   beq.s      MorFinish             ; if not....
   SysCall    Forbid                ; ensure WB doesn't dump us till we're done
   move.l     WBMsg,a1              ; get orig mesg from WB
   Call       ReplyMsg              ; reply it, we're leaving!
MorFinish
   move.l     RememberKey,d0        ; give back AllocRemember mem! (if any)
   beq.s      2$
   lea        RememberKey,a0
   moveq.l    #1,d0
   IntCall    FreeRemember
2$
   move.l     GFXBase,d0            ; close any open libs
   beq.s      3$
   bsr        _CloseLib
3$
   move.l     INTBase,d0            ; close any open libs
   beq.s      4$
   bsr        _CloseLib
4$
   move.l     MATHBase,d0           ; close any open libs
   beq.s      5$
   bsr        _CloseLib
5$
   move.l     TRANSBase,d0          ; close any open libs
   beq.s      6$
   bsr        _CloseLib
6$
   move.l     DOSBase,d0            ; close any open libs
   beq.s      7$
   bsr        _CloseLib
7$
   move.l     (SP)+,d0              ; get d0 back off the stack
   move.l     StackPTR,SP           ; restore Stack PTR
   rts


_StartError
   moveq      #CantInitSystem,d0
   bra        _Error

_OpenLib
   move.l     #0,d0
   SysCall    OpenLibrary
   rts

_CloseLib
   move.l     d0,a1
   SysCall    CloseLibrary
   rts

_OpenDos
   lea        DOSName,a1
   bsr        _OpenLib
   move.l     d0,DOSBase
   beq        _StartError
   rts

_OpenLibs

   IFD GFX
   lea        GFXName,a1
   bsr        _OpenLib
   move.l     d0,GFXBase
   beq        _StartError
   ENDC

   IFD INT
   lea        INTName,a1
   bsr        _OpenLib
   move.l     d0,INTBase
   beq        _StartError
   ENDC

   IFD FFP
   lea        MATHName,a1
   bsr        _OpenLib
   move.l     d0,MATHBase
   beq        _StartError
   ENDC

   IFD TRA
   lea        TRANSName,a1
   bsr        _OpenLib
   move.l     d0,TRANSBase
   beq        _StartError
   ENDC
   rts

; ****  Data Storage ***

StackPTR
   dc.l       0                     ; stack pointer storage
TaskPTR
   dc.l       0                     ; this task struct storage
DOSBase
   dc.l       0                     ; PTR to DosLib jump table
GFXBase
   dc.l       0                     ;       Graphics
INTBase
   dc.l       0                     ;       Intuition
MATHBase
   dc.l       0                     ;       MathFFP
TRANSBase
   dc.l       0                     ;       MathTrans
ARPBase
   dc.l       0                     ;       ARP lib
RememberKey
   dc.l       0                     ; Program wide AllocRemember PTR
Command
   dc.l       0                     ; Address of command tail
CmdLen
   dc.l       0                     ; length of command tail
WBMsg
   dc.l       0                     ; address of WB Message (if any)
StdIn
   dc.l       0                     ; address of INPUT file
StdOut
   dc.l       0                     ; address of OUTPUT file
StdErr
   dc.l       0                     ; address of ERROR file
EndFromWB
   dc.l       0                     ; set to 1 if from WB
EndFromCLI
   dc.l       0                     ; set to 1 if from CLI
DOSName
   dc.b       'dos.library',0       ; all these names for OpenLibrary
   EvenPC
GFXName
   dc.b       'graphics.library',0
   EvenPC
INTName
   dc.b       'intuition.library',0
   EvenPC
MATHName
   dc.b       'mathffp.library',0
   EvenPC
TRANSName
   dc.b       'mathtrans.library',0
   EvenPC
ARPName
   dc.b       'arp.library',0
   EvenPC
NewConsole
   dc.b       'CON:20/20/600/180/WBConsole'
   EvenPC
