******************************************************************************* * "Startup.asm" * * $VER: Startup_asm 3.4 (5.9.95) * * Copyright © 1995 by Kenneth C. Nilsen/Digital Surface * This source is public domain. * * For instructions read the Startup_Asm.doc or see the Startup_example.s * *SUMMARY: * *StartSkip = 0 or 1 (0 = wb/cli, 1=cli only (eg. from AsmOne)) *Processor = 0 or 680x0 *MathProc = 0 or 6888x/68040 * *Init: Version <"PrgName ver.rev (date)"> (opt) * TaskName <"new task name in qvotes"> (opt) * TaskPri (opt) * DefLib , (opt) * DefEnd ;must end the "Init:" section ALWAYS! (required!) * *Start: LibBase (opt) * StartFrom = 0 (CLI) or <>0 (WB) in D0 (opt) * TaskPointer = pointer to taskstructure (D0) (opt) * NextArg = pointer to next argument or 0 (D0) (opt) * Return (with RTS) (recommended) * ******************************************************************************* zyxMax = 17 ;max no. of libraries for AllocMem() zyxBufZ = 308 ;size of format buffer in bytes for AllocMem() ; (these above settings will require 512 bytes allocated memory (0.5Kb)) *-----------------------------------------------------------------------------* * Macros for Startup.asm *-----------------------------------------------------------------------------* Return Macro moveq #\1,d0 ;* if you use rtn code >127, change to "move.l" rts ;exit our program EndM DefLib Macro ;, lea \1NamX(pc),a1 ;make exclusive library namelabel move.l a1,(a5)+ ;put name into our buffer (if print) move.l a1,zyxNx ;store name in local label moveq #\2,d0 ;* if you use ver >127, change this to "move.l" move.l d0,(a5)+ ;store version in our buffer move.l d0,zyxVx ;store version in local label jsr -552(a6) ;try open library move.l d0,(a5)+ ;store result in our buffer move.l d0,\1basX ;store result in global label bne.b \1zyx ;if <>0 then ok bsr.w zyxLibR ;print error message bra.b \1zyx ;go on... \1basX dc.l 0 \1NamX dc.b "\1.library",0 ;library name macro even \1zyx EndM DefEnd Macro move.l #-1,(a5) ;this terminate our library list rts ;exit init section EndM LibBase Macro ; move.l \1basX(pc),a6 ;get library base with exclusive name EndM TaskName Macro ;<"name-on-task"> move.l $4.w,a6 ;exec base jsr -132(a6) ;Disable() move.l zyxTask(pc),a0 ;get stored task pointer to our task move.l #.TaskN,10(a0) ;get ptr. to new name and store jsr -138(a6) ;Enable() bra.b .zyxTsk ;go on... .TaskN dc.b \1 ;task name macro dc.b 0 ;null terminate even .zyxTsk EndM TaskPri Macro ; move.l $4.w,a6 ;execbase move.l zyxTask(pc),a1 ;get stored task pointer moveq #\1,d0 ;get new task priority jsr -300(a6) ;SetTaskPri() EndM TaskPointer Macro move.l zyxTask(pc),d0 ;give pointer to task in d0 EndM StartFrom Macro move.l RtnMess(pc),d0 ;if started from WB, d0<>0 EndM Version Macro bra.w .zyxVer ;jump garbage code :) dc.b "$VER: " ;init header dc.b \1 ;get rest of string from macro dc.b 0 ;null terminate even .zyxVer EndM NextArg Macro move.l zyxArgP(pc),d0 ;get address to argument string beq.b *+8 ;none? (from WB) then skip move.l d0,a0 ;use pointer bsr.w zyxGArg ;go to our internal routine move.l a0,zyxArgP ;update argument pointer tst.l d0 ;set/unset Z flag EndM *-----------------------------------------------------------------------------* * MAIN routine: *-----------------------------------------------------------------------------* GoZYX move.l a0,-(sp) ;store argument pointer move.l d0,zyxArgL ;store length of arg. string move.l a0,zyxArgP ;store arg. pointer in internal label move.l $4.w,a6 ;exec base move.l #zyxBufZ,d0 ;set buffer size move.l #$10001,d1 ;requirements (public, clear) jsr -198(a6) ;AllocMem() move.l d0,zyxBuff ;store result in label beq.w .DOS ;Null? then exit sub.l a1,a1 ;a1=0 (this task) jsr -294(a6) ;FindTask() move.l d0,a4 ;copy result move.l d0,zyxTask ;store for internal use tst.l 172(a4) ;where we started from (wb/cli) bne.b .chkPro ;<>0 then cli moveq #StartSkip,d0 ;check if we wanne skip (eg. AsmOne) bne.b .chkPro ;yepp, then skip lea 92(a4),a0 ;get message port address jsr -384(a6) ;WaitPort() lea 92(a4),a0 ;get message port address jsr -372(a6) ;GetMsg() move.l d0,RtnMess ;store message pointer in label .chkPro move.w 296(a6),d5 ;AttnFlags in execbase and.l #$ff,d5 ;we only need the first byte move.l #Processor,d7 ;processor we want beq.w .ProOk ;null? then any will do, skip this part cmp.l #68000,d7 ;or 68000? beq.w .ProOk ;then skip too... .nxPro1 cmp.l #68010,d7 ;68010? bne.b .nxPro2 ;no, check next and.b #$cf,d5 ;check bits bne.w .ProOk ;we got a 68010 or higher bra.w .ProErr ;we got lower, we can't start... .nxPro2 cmp.l #68020,d7 ;same as above, just higher processor bne.b .nxPro3 and.b #$ce,d5 bne.w .ProOk bra.b .ProErr .nxPro3 cmp.l #68030,d7 bne.b .nxPro4 and.b #$cc,d5 bne.b .ProOk bra.b .ProErr .nxPro4 cmp.l #68040,d7 bne.b .nxPro5 and.b #$c8,d5 bne.b .ProOk bra.b .ProErr .nxPro5 cmp.l #68060,d7 ;we want a 68060 (yes, we do :) ) bne.b .ProWho ;not? then I dont know about any higher btst #7,d5 ;test if it is a 68060 we're using beq.b .ProErr ;nope btst #6,d5 ;are you sure? bne.b .ProOk ;yepp, continue bra.b .ProErr ;not a 060, print error message .ProWho lea ProcWho(pc),a0 ;unknown processor required, print move.l #Processor,ProcNum ;message about it. bra.b .format .ProErr lea ProcErr(pc),a0 ;we don't got the processor required move.l #Processor,ProcNum ;print message about it... .format lea ProcNum(pc),a1 bsr.w zyxPrt ;jump to our cli print routine bra.w .End .ProOk move.l #MathProc,d7 ;time to check for math-co-processor beq.w .MathOk ;null? then any will do... cmp.l #68881,d7 ;a 68881? bne.b .Math2 ;no check next and.b #$70,d5 ;check flags bne.b .MathOk ;we got it bra.b .MathEr ;sorry... .Math2 cmp.l #68882,d7 ;sae as above bne.b .Math3 and.b #$60,d5 bne.b .MathOk bra.b .MathEr .Math3 cmp.l #68040,d7 ;we have a 68040 with FPU not 881/882 bne.b .MathEr ;unknown FPU if any else... btst #6,d5 ;we got it? bne.b .MathOk ;yepp, continue .MathEr lea MathErr(pc),a0 ;print error message... move.l #MathProc,ProcNum bra.w .format .MathOk bsr.w zyxLibO ;oki, open our libraries tst.w zyxLR ;any error? bne.b .noShow ;yepp, don't jump to main program move.l zyxArgP(pc),a0 ;get arg. pointer move.l zyxArgL(pc),d0 ;get arg. length bsr.w Start ;start main program move.l d0,zyxVal ;store return code .noShow bsr.w zyxLibC ;close libraries if any .End move.l zyxBuff(pc),d0 ;get pointer to our buffer beq.b .noBuff ;no buffer?!? move.l d0,a1 ;copy pointer move.l #zyxBufZ,d0 ;length of buffer jsr -210(a6) ;FreeMem() .noBuff tst.l RtnMess ;from WB? beq.w .DOS ;nope, from CLI jsr -132(a6) ;Disable() move.l RtnMess(pc),a1 ;put message in a1 jsr -138(a6) ;Enable() .DOS movem.l (sp)+,a0 ;restore stack, put arg. pointer back move.l zyxVal(pc),d0 ;set return code rts ;BYE! :) zyxDo move.b d0,(a3)+ ;for RawDoFmt(), process routine rts zyxPrt movem.l d0-a6,-(sp) ;store regs. on stack lea zyxDo(pc),a2 ;process move.l zyxBuff(pc),a3 ;format buffer jsr -522(a6) ;RawDoFmt() moveq #0,d0 ;any version lea zyxDos(pc),a1 ;ptr. to dos.library name jsr -552(a6) ;OpenLibrary() tst.l d0 ;failed? beq.b .exit ;jepp, exit move.l d0,a6 ;use dosbase jsr -60(a6) ;Output() move.l d0,d1 ;copy, set Z, failed? beq.b .clDos ;no output -> close dos.library move.l zyxBuff(pc),a0 ;get ptr. to our buffer move.l a0,d2 ;copy pointer moveq #0,d3 ;clear D3 (length of buffer) .count move.b (a0)+,d0 ;get one char beq.b .cntEnd ;null? yepp, found end... addq #1,d3 ;nope, add one in length bra.b .count ;continue .cntEnd jsr -48(a6) ;print buffer to output handler (CLI) .clDos move.l a6,a1 ;copy dosbase to a1 move.l $4.w,a6 ;get exebase jsr -414(a6) ;CloseLibrary() .exit movem.l (sp)+,d0-a6 ;restore stack rts ;return zyxLibO move.l #4*3*zyxMax,d0 ;library buffer size 12*zyxMax (192) move.l #$10001,d1 ;any mem, clear it jsr -198(a6) ;AllocMem() move.l d0,zyxMem ;store result beq.b .memErr ;null? then error move.l d0,a5 ;use buffer bsr.w Init ;jump to init section (see macros) rts ;done .memErr lea zyxFR(pc),a0 ;get format text lea zyxMeR(pc),a1 ;get input string bsr.w zyxPrt ;print message about low memory move.w #-1,zyxLR ;failed, don't start main program rts ;return zyxLibC move.l $4.w,a6 ;execbase move.l zyxMem(pc),d0 ;library buffer beq.w .noLibs ;null? then no libraries move.l d0,a5 ;use pointer .loop cmp.l #-1,(a5) ;end? beq.b .clEnd ;yepp, then done! move.l 8(a5),d0 ;get library base beq.b .noCl ;null? then this lib. failed to open move.l d0,a1 ;use base jsr -414(a6) ;CloseLibrary() .noCl lea 12(a5),a5 ;get next library base bra.b .loop ;continue .clEnd move.l zyxMem(pc),a1 ;get lib. buffer pointer move.l #4*3*zyxMax,d0 ;size jsr -210(a6) ;FreeMem() .noLibs rts ;return zyxLibR move.w #-1,zyxLR ;if any errors, set error flag lea zyxLib(pc),a0 lea zyxNx(pc),a1 bsr.w zyxPrt ;print library name lea zyxVer(pc),a0 lea zyxVx(pc),a1 bsr.w zyxPrt ;print library version rts ;return zyxGArg move.b (a0)+,d0 ;get a char from arg. line beq.w .end ;null? end of line cmp.b #10,d0 ;linefeed? beq.w .end ;end of line cmp.b #9,d0 ;tab? beq.b zyxGArg ;get another char cmp.b #32,d0 ;space? beq.b zyxGArg ;get another char move.l zyxBuff(pc),a1 ;our text buffer lea -1(a0),a0 ;go back one byte on arg. line .copy move.b (a0)+,d0 ;copy char to d0 beq.b .stop ;null? then stop copy cmp.b #10,d0 ;linefeed? beq.b .stop ;stop copy cmp.b #32,d0 ;space? beq.b .eol ;then this arg. is done .cont cmp.b #'*',d0 ;asterix? beq.b .chkSpc ;check for special functions cmp.b #'"',d0 ;qvote? beq.b .toggle ;toggle copy mode .noChk move.b d0,(a1)+ ;copy passed char to our buffer .cont2 bra.b .copy ;continue copy .chkSpc cmp.b #'"',(a0) ;a qvote want to be used? bne.b .chk2 ;no, check for a linefeed then... move.b #'"',(a1)+ ;copy a qvote to our buffer lea 1(a0),a0 ;skip one byte (2(*")->1(")) bra.b .copy ;continue copy argument .chk2 cmp.b #'n',(a0) ;a linefeed? bne.b .noChk ;nope, skip special funcs. move.b #10,(a1)+ ;copy a linefeed to our buffer lea 1(a0),a0 ;make 2 -> 1 bra.b .copy ;continue copy .toggle tst.w zyxQ ;already toggled? beq.b .set ;nope, then toggle clr.w zyxQ ;re toggle bra.b .stop ;end of argument .set move.w #-1,zyxQ ;toggle so we can use space in arg. bra.b .cont2 ;continue copying argument .eol tst.w zyxQ ;end of line -> toggled? bne.b .cont ;jepp, continue .stop tst.w zyxQ ;toggled? bne.b .end ;jepp,don't care about this arg (error) clr.b (a1) ;terminate buffer move.l zyxBuff(pc),d0 ;pointer to extracted argument rts ;return to macro .end moveq #0,d0 ;no more args rts ;return to macro RtnMess dc.l 0 ;pointer to WB message ProcNum dc.l 0 ;prossecor wanted zyxArgL dc.l 0 ;argument line length zyxArgP dc.l 0 ;pointer to argument string zyxVal dc.l 0 ;return code zyxMem dc.l 0 ;pointer to library buffer zyxNx dc.l 0 ;temp lib. name zyxVx dc.l 0 ;temp lib. version zyxTask dc.l 0 ;pointer to task structure zyxLR dc.w 0 ;error flag zyxQ dc.w 0 ;toggle flag for qvotes zyxBuff dc.l 0 ;pointer to string buffer zyxMeR dc.l zyxMemR ;pointer to a format string zyxDos dc.b 'dos.library',0 zyxLib dc.b "Couldn't open %s ",0 zyxVer dc.b 'version %ld.',10,0 zyxMemR dc.b 'Not enough memory!',10,0 zyxFR dc.b '%s',0 ProcWho dc.b 'INTERN: %ld ?',10,0 ProcErr dc.b 'This program require %ld+',10,0 MathErr dc.b 'This program need %ld FPU',10,0 even