home *** CD-ROM | disk | FTP | other *** search
/ Club Amiga de Montreal - CAM / CAM_CD_1.iso / files / 508.lha / IO_Expansion_Board / IOpatch / IOpatch.asm < prev   
Assembly Source File  |  1991-05-06  |  23KB  |  966 lines

  1. *****************************************************************************
  2. * Program:  IOpatch.asm - ©1990 by Dan Babcock
  3. * Function: This program patches the exec OpenDevice call, and allows the
  4. *           user to select a serial or parallel unit.
  5. *
  6. * Author:   Dan Babcock
  7. * History:  02/07/90 DB V0.50 Created
  8. *           09/22/90 DB V0.51 Added code to prevent redundant requesters
  9. *                             in certain cases.
  10. *           12/10/90 JL V0.52 Added code to parse the command line, and
  11. *                             allow various arguments (outlined below).
  12. *           01/12/91 DB V0.53 Misc. enhancements
  13. *
  14. * [To all: Please don't forget to bump the revision numbers if you do *any*
  15. *          modifications at all.  -Jeff]
  16. *****************************************************************************
  17. * Program:  SelectWindow - ©1990 by The Puzzle Factory
  18. * Function: Get the users preference for which unit to open.
  19. *
  20. * Author:   Jeff Lavin
  21. * History:  01/29/90 JL V0.50 Created
  22. *           02/07/90 DB V0.51 Modified to include an "Internal" gadget.
  23. *           08/22/90 JL V0.52 Added borders to the gadgets.
  24. *                             Converted to Macro68 & new syntax.
  25. *           09/12/90 JL V0.53 Dynamically size everything now.
  26. *           09/26/90 JL V0.54 Fixed lores display problem.
  27. *           11/16/90 JL V0.55 Rearrainged gadgets; Gadget 0 is now full width.
  28. *
  29. * [To all: Please don't forget to bump the revision numbers if you do *any*
  30. *          modifications at all.  -Jeff]
  31. *****************************************************************************
  32.  
  33.  
  34. *****************************************************************************
  35. * NAME
  36. *     IOpatch - This program patches the exec OpenDevice call. The user
  37. *     puts this program in his startup-sequence or whereever before he runs
  38. *     his terminal progs, BBS's and whatnot - if these do not permit the
  39. *     user to change the device/unit info. If they do, this utility is not
  40. *     needed, obviously.
  41. *
  42. * INPUTS
  43. *
  44. *     1> IOpatch       ;Check OpenDevice() calls for serial & parallel device
  45. *     1> IOpatch -a    ;Check OpenDevice() calls for serial & parallel device
  46. *     1> IOpatch -s    ;Check OpenDevice() calls for serial device only
  47. *     1> IOpatch -p    ;Check OpenDevice() calls for parallel device only
  48. *     1> IOpatch -q    ;Replaces previous vector for OpenDevice() calls.
  49. *     1> IOpatch ?     ;Prints these instructions
  50. *
  51. * RESULTS
  52. *     OpenDevice() will use the either:
  53. *
  54. *          the serial.device or the newser.device
  55. *          the parallel.device or the eightbit.device
  56. *
  57. *     with the proper unit number depending on which device was to have been
  58. *     opened, and what the user selected from the requester.
  59. *
  60. * NOTES
  61. *     There is one complication: I noticed during testing that most term
  62. *     programs open and close the serial.device several times during their
  63. *     startup routines. This is rather stupid of them, of course, and it
  64. *     unfortunately results in many redundant requesters.
  65. *     This version tries its best to avoid this problem by keeping track of
  66. *     tasks that have opened the serial/parallel device and re-using
  67. *     previously specified (by the user via the requester) unit number.
  68. *     One last note: this program copies itself into dynamically allocated
  69. *     memory, so the user does not have to "run" it.
  70. *
  71. ******************************* tear here ***********************************
  72.  
  73. ;Set Tabs           |       |                 |       |
  74.  
  75.     ifnd    __m68
  76.     fail    'Wrong assembler!'
  77.     endc
  78.     exeobj
  79.     macfile    'Includes:IOexp.i'    ;The One & Only include file
  80.     objfile    'IOpatch'
  81.  
  82. TASKTABLESIZE    equ    32
  83.  
  84. Dispatcher    moveq    #-1,d2    ;serflag default
  85.     moveq    #-1,d3    ;parflag default
  86.     moveq    #0,d6    ;quit flag default
  87.     moveq    #0,d5    ;Clear WBenchMsg
  88.  
  89.     movea.l    (SysBase).w,a6
  90.     movea.l    (ThisTask,a6),a2
  91.     tst.l    (pr_CLI,a2)    ;Are we a child of WBench?
  92.     bne.b    FromCLI    ;Branch if no
  93.  
  94.     lea    (pr_MsgPort,a2),a0
  95.     SYS    WaitPort
  96.     lea    (pr_MsgPort,a2),a0
  97.     SYS    GetMsg
  98.     move.l    d0,d5    ;WBenchMsg
  99.     bra.w    SetPatch    ;No args from WBench
  100.  
  101. FromCLI    lea    (a0,d0.w),a1
  102. ..    cmpi.b    #' ',-(a1)    ;Eat trailing garbage
  103.     dbhi    d0,..
  104.     blt.b    SetPatch    ;If no arguments, don't parse
  105.     clr.b    (1,a1)    ;Null terminate the string
  106.  
  107. Parse    moveq    #0,d0
  108.     move.b    (a0)+,d0
  109.     beq.b    SetPatch    ;Null ends
  110.     cmpi.b    #' ',d0    ;Skip spaces
  111.     beq.b    Parse
  112.     cmpi.b    #'?',d0    ;Instruct?
  113.     beq.b    4$    ;"Usage:..."
  114.     cmpi.b    #'-',d0    ;Look for "-" char
  115.     bne.b    Parse    ;Skip til we find one
  116.     move.b    (a0)+,d0    ;Get next char
  117.     beq.b    SetPatch    ;Null ends
  118.     cmpi.b    #'a',d0    ;Convert to U/C
  119.     blo.s    1$
  120.     cmpi.b    #'z',d0
  121.     bhi.s    1$
  122.     subi.b    #$20,d0
  123.  
  124. 1$    cmpi.b    #'A',d0    ;[A]ll
  125.     bne.b    2$
  126.     seq    d2    ;serflag
  127.     seq    d3    ;parflag
  128.     bra.b    SetPatch
  129.  
  130. 2$    cmpi.b    #'S',d0    ;[S]erial only
  131.     bne.b    3$
  132.     seq    d2    ;serflag
  133.     sne    d3    ;parflag
  134.     bra.b    SetPatch
  135.  
  136. 3$    cmpi.b    #'P',d0    ;[P]arallel only
  137.     bne.b    4$
  138.     sne    d2    ;serflag
  139.     seq    d3    ;parflag
  140.     bra.b    SetPatch
  141.  
  142. 4$    cmpi.b    #'Q',d0    ;[Q]uit
  143.     bne.w    Instruct
  144.     seq    d6    ;quit flag
  145.  
  146. ;Note that multitasking is disabled (via Forbid) throughout the install
  147. ;code for 100% safety.
  148. ;First, check to see whether this program has been run before.
  149.  
  150. SetPatch    lea    (serflag,pc),a0
  151.     move.b    d2,(a0)
  152.     lea    (parflag,pc),a0
  153.     move.b    d3,(a0)
  154.  
  155.     movea.l    (SysBase).w,a6
  156.     SYS    Forbid
  157.  
  158.     lea    (portname,pc),a1
  159.     SYS    FindPort
  160.     move.l    d0,d2
  161.     tst.l    d2
  162.     bne.b    installed    ;Go if already installed
  163.  
  164. ;Not installed, so allocate memory and copy
  165.  
  166.     move.l    #enddispatchcode-startdispatchcode,d7
  167.     move.l    d7,d0
  168.     moveq    #0,d1    ;No special attributes
  169.     SYS    AllocMem
  170.     tst.l    d0
  171.     bne.b    allocok
  172.  
  173. panic    tst.l    d5    ;WBenchMsg
  174.     beq.b    1$
  175.     movea.l    d5,a1    ;We're already forbidden
  176.     SYS    ReplyMsg    ;Return msg
  177.     bra.b    2$
  178.  
  179. 1$    SYS    Permit
  180. 2$    moveq    #-1,d0
  181.     rts
  182.  
  183. allocok    movea.l    d0,a5
  184.     movea.l    d0,a1
  185.     lea    (startdispatchcode,pc),a0
  186.     move.l    d7,d0
  187.     SYS    CopyMem
  188.     lea    (panic,pc),a4
  189.     jmp    (a5)    ;Go to startdispatchcode
  190.  
  191. installed    tst.b    d6    ;Go if already installed
  192.     beq.b    quitdispatch    ;& quit flag set
  193.  
  194. ;Remove the patch (port addr in d2)
  195.  
  196.     movea.l    d2,a2
  197.     movea.l    (MP_SIZE,a2),a3    ;Get start addr of res code
  198.     lea    (newopendevice-startdispatchcode,a3),a4 ;Get addr of replacement
  199.     cmpa.l    (_LVOOpenDevice+2,a6),a4 ;Still there?
  200.     bne.b    panic    ;No, so can't deinstall
  201.     lea    (newremtask-startdispatchcode,a3),a4 ;Get addr of replacement
  202.     cmpa.l    (_LVORemTask+2,a6),a4 ;Still there?
  203.     bne.b    panic    ;No, so can't deinstall
  204.  
  205.     move.l    (oldopenvec-startdispatchcode,a3),d0
  206.     movea.w    #_LVOOpenDevice,a0
  207.     movea.l    a6,a1
  208.     SYS    SetFunction
  209.  
  210.     move.l    (oldremtask-startdispatchcode,a3),d0
  211.     movea.w    #_LVORemTask,a0
  212.     movea.l    a6,a1
  213.     SYS    SetFunction
  214.  
  215.     movea.l    a2,a1    ;Deallocate memory etc.
  216.     SYS    RemPort
  217.  
  218.     moveq    #MP_SIZE+4,d0
  219.     movea.l    a2,a1
  220.     SYS    FreeMem    ;Free message port
  221.  
  222.     move.l    #enddispatchcode-startdispatchcode,d0
  223.     movea.l    a3,a1
  224.     SYS    FreeMem    ;Free the code
  225.  
  226. quitdispatch    tst.l    d5    ;WBenchMsg
  227.     beq.b    1$
  228.     movea.l    d5,a1    ;We're already forbidden
  229.     SYS    ReplyMsg    ;Return msg
  230.     bra.b    2$
  231.  
  232. 1$    SYS    Permit
  233. 2$    moveq    #0,d0
  234.     rts
  235.  
  236. Instruct    tst.l    d5    ;WBenchMsg
  237.     beq.b    .OpenDos
  238.     addq.b    #1,(TDNestCnt,a6)    ;Forbid so WBench won't
  239.     movea.l    d5,a1    ; UnloadSeg() us
  240.     SYS    ReplyMsg    ;Return msg
  241.     bra.b    .Exit
  242.  
  243. .OpenDos    lea    (DosName,pc),a1
  244.     moveq    #0,d0
  245.     SYS    OpenLibrary    ;Open dos.library
  246.     tst.l    d0
  247.     beq.b    .Exit    ;Failed!
  248.  
  249.     move.l    a6,-(sp)
  250.     movea.l    d0,a6
  251.     SYS    Output    ;Get output filehandle
  252.     move.l    d0,d1    ;Filehandle
  253.     beq.b    .CloseDos
  254.     lea    (Help.msg,pc),a0
  255.     move.l    a0,d2    ;Buffer
  256.     move.l    #Help_Len,d3    ;Length
  257.     SYS    Write    ;Help the user
  258.  
  259. .CloseDos    movea.l    a6,a1
  260.     movea.l    (sp)+,a6
  261.     SYS    CloseLibrary    ;Close the dos.library
  262. .Exit    moveq    #0,d0
  263.     rts
  264.  
  265.  
  266. ;***** All the following code is copied into dynamically allocated mem
  267.  
  268. ;Add a port to indicate that we're installed
  269. ;Allocate memory for the port
  270.  
  271. startdispatchcode    moveq    #MP_SIZE+4,d0    ;MsgPort+4 bytes of private info
  272.     moveq    #1,d1
  273.     swap    d1    ;CLEAR parm
  274.     SYS    AllocMem
  275.     tst.l    d0
  276.     bne.b    somememleft
  277.  
  278.     move.l    d7,d0    ;Uh oh. The poor user is out of memory.
  279.     move.l    a4,-(sp)    ;Return addr
  280.     movea.l    a5,a1
  281.     jmp    (_LVOFreeMem,a6)    ;RTS takes us back to 'panic'
  282.  
  283. somememleft    movea.l    d0,a1
  284.     lea    (portname,pc),a0
  285.     move.l    a0,(LN_NAME,a1) 
  286.     move.l    a5,(MP_SIZE,a1)    ;Private info - addr of res code 
  287.     SYS    AddPort
  288.  
  289.     movea.w    #_LVOOpenDevice,a0 ;Patch into OpenDevice
  290.     movea.l    a6,a1
  291.     lea    (newopendevice,pc),a2
  292.     move.l    a2,d0
  293.     SYS    SetFunction
  294.  
  295.     lea    (oldopenvec,pc),a0
  296.     move.l    d0,(a0)
  297.  
  298.     movea.w    #_LVORemTask,a0 ;Patch into RemTask
  299.     movea.l    a6,a1
  300.     lea    (newremtask,pc),a2
  301.     move.l    a2,d0
  302.     SYS    SetFunction
  303.     lea    (oldremtask,pc),a0
  304.     move.l    d0,(a0)
  305.  
  306.     tst.l    d5    ;WBenchMsg
  307.     beq.b    1$
  308.     movea.l    d5,a1    ;We're already forbidden
  309.     SYS    ReplyMsg    ;Return msg
  310.     bra.b    2$
  311.  
  312. 1$    SYS    Permit 
  313. 2$    moveq    #0,d0
  314.     rts
  315.  
  316.  
  317. ;*** NOTE: A zero TCB (in A1) indicates self removal !!!!
  318. ;(this little fact nearly drove me nuts during debugging!)
  319.  
  320. newremtask:
  321.     move.l    a1,d0
  322.     bne.b    .L2
  323.     move.l    a1,-(sp)
  324.     SYS    FindTask
  325.     movea.l    (sp)+,a1
  326. .L2    move.l    a1,-(sp)
  327.     SYS    Forbid
  328.     movea.l    (sp)+,a1
  329.  
  330.     moveq    #TASKTABLESIZE-1,d1
  331.     lea    (sertasklist,pc),a0
  332. ..    cmp.l    (a0)+,d0
  333.     addq.l    #2,a0
  334.     dbeq    d1,..
  335.     bne.b    .L1
  336.     clr.l    (-6,a0)
  337. .L1
  338.  
  339.     moveq    #TASKTABLESIZE-1,d1
  340.     lea    (partasklist,pc),a0
  341. ..    cmp.l    (a0)+,d0
  342.     addq.l    #2,a0
  343.     dbeq    d1,..
  344.     bne.b    .L3
  345.     clr.l    (-6,a0)
  346. .L3
  347.  
  348.     move.l    a1,-(sp)
  349.     SYS    Permit
  350.     movea.l    (sp)+,a1
  351.     movea.l    (oldremtask,pc),a0
  352.     jmp    (a0)
  353.  
  354. newopendevice    movem.l d6-d7/a2-a5,-(sp)
  355.     suba.l    a5,a5    ;Sanity check
  356.     tst.l    d0    ;Check unit number
  357.     bne    oldopenjump    ;If nonzero, skip menu
  358.     lea    (serunitexists,pc),a4
  359.     lea    (serflag,pc),a2
  360.     tst.b    (a2)+    ;Want to check serial device?
  361.     beq.b    1$    ;Branch if no
  362.     movea.l    a0,a3
  363. ..    cmpm.b    (a2)+,(a3)+
  364.     bne.b    1$
  365.     tst.b    (-1,a2)
  366.     bne.b    ..
  367.     lea    (newserialname,pc),a5
  368.     moveq    #0,d5
  369.     bra.b    2$
  370.  
  371. 1$    lea    (parflag,pc),a2
  372.     tst.b    (a2)+    ;Want to check parallel device?
  373.     beq.b    2$    ;Branch if no
  374.     movea.l    a0,a3
  375. ..    cmpm.b    (a2)+,(a3)+
  376.     bne.w    nogood
  377.     tst.b    (-1,a2)
  378.     bne.b    ..
  379.     lea    (newparallelname,pc),a5
  380.     moveq    #1,d5
  381.     addq.w    #4,a4    ;Point to parunitexists
  382.  
  383. ;One last check: if this task has previously opened either the serial.device
  384. ;or the parallel.device, use the same unit number (stored in tasklist) rather
  385. ;than bothering the user.
  386.  
  387. 2$    cmpa.l    #0,a5    ;Sanity check
  388.     beq    nogood    ;User has disabled both flags!
  389.  
  390.     movem.l    d0/d1/a0/a1,-(sp)
  391.     move.l    (ThisTask,a6),d6
  392.     SYS    Forbid
  393.     moveq    #15,d7
  394.     lea    (sertasklist,pc),a2
  395.     tst.l    d5
  396.     beq.b    .skippar
  397.     lea    (partasklist,pc),a2
  398. .skippar:
  399. ..    cmp.l    (a2)+,d6    
  400.     addq.l    #2,a2
  401.     dbeq    d7,..
  402.     bne.b    popup
  403.     SYS    Permit
  404.     movem.l    (sp)+,d0/d1/a0/a1
  405.     moveq    #0,d0
  406.     move.w    (-2,a2),d0
  407.     bra.b    skipmenu
  408.  
  409. popup    SYS    Permit
  410.     movem.l    (sp)+,d0/d1/a0/a1
  411.  
  412. ;pop up a menu
  413.  
  414.     move.l    (a4),d0    ;serunitexists/parunitexists
  415.     movem.l    d1-d7/a0-a6,-(sp)
  416.     bsr    SelWin    ;Get input from the user
  417.     movem.l    (sp)+,d1-d7/a0-a6
  418.     tst.l    d0    ;Ok?
  419.     bpl.b    contdisp
  420.  
  421. ;The user is out of memory; signal an error
  422.  
  423.     moveq    #-1,d0 
  424.     move.b    d0,(IO_ERROR,a1)    ;Set error in the IO Request
  425.     bra.b    endnewopen
  426.  
  427. contdisp:
  428.  
  429. ;store the TCB ptr and the unit# in tasklist for future use
  430.  
  431. ;search for an empty slot
  432.     movem.l    d0/d1/a0/a1,-(sp)
  433.     SYS    Forbid
  434.     lea    (sertasklist,pc),a2
  435.     tst.l    d5
  436.     beq.b    .skippar
  437.     lea    (partasklist,pc),a2
  438. .skippar:
  439.     moveq    #TASKTABLESIZE-1,d7
  440. ..    tst.l    (a2)+
  441.     addq.w    #2,a2
  442.     dbeq    d7,..
  443.     bne.b    oldtask    ;Full! (not likely to happen)
  444.     SYS    Permit
  445.     movem.l    (sp)+,d0/d1/a0/a1
  446.     move.l    d6,(-6,a2)
  447.     move.w    d0,(-2,a2)    
  448.     bra.b    skipmenu
  449. oldtask:
  450.     SYS    Permit
  451.     movem.l    (sp)+,d0/d1/a0/a1
  452.  
  453. skipmenu:
  454.     tst.l    d0
  455.     beq.b    oldopenjump    ;If zero, use std device
  456.     subq.l    #1,d0
  457.  
  458. oldtask1    movea.l    a5,a0    ;newserialname/newparallelname
  459. nogood 
  460. oldopenjump    movea.l    (oldopenvec,pc),a3
  461.     jsr    (a3)
  462. endnewopen    movem.l    (sp)+,d6-d7/a2-a5
  463.     rts
  464.  
  465. oldopenvec    dl    0 
  466. oldremtask    dl    0
  467.  
  468. ;These variables should be set by the code that checks for the presence
  469. ;of units 3 and 4.  Right now, they're hard-coded to say that they exist.
  470.  
  471. serunitexists    dl    1
  472. parunitexists    dl    1
  473.  
  474. ;Note: TASKTABLESIZE entries, arranged like so:
  475. ;Ptr to TCB (longword)
  476. ;Unit number (word)
  477.  
  478. sertasklist:
  479.     dcb.l    TASKTABLESIZE,0
  480.     dcb.w    TASKTABLESIZE,0
  481. partasklist:
  482.     dcb.l    TASKTABLESIZE,0
  483.     dcb.w    TASKTABLESIZE,0
  484.  
  485. portname    cstr    'IOExp dispatcher V1.10 ©1990 by Dan Babcock *INSTALLED*'
  486. serflag    db    $FF    ;Default = ON
  487. oldserialname    cstr    'serial.device'
  488. newserialname    MYDEVNAME
  489. parflag    db    $FF    ;Default = ON
  490. oldparallelname    cstr    'parallel.device'
  491. newparallelname    PARDEVNAME
  492. DosName    cstr    'dos.library'
  493.  
  494. Help.msg    db    'I/O Expansion Dispatcher V1.10 ©1990 by Dan Babcock',10
  495.     db    'Usage:',10,10
  496.     db    ' IOpatch     ;Check OpenDevice() calls for serial & parallel device',10
  497.     db    ' IOpatch -a  ;Check OpenDevice() calls for serial & parallel device',10
  498.     db    ' IOpatch -s  ;Check OpenDevice() calls for serial device only',10
  499.     db    ' IOpatch -p  ;Check OpenDevice() calls for parallel device only',10
  500.     db    ' IOpatch -q  ;Replaces previous vector for OpenDevice() calls.',10
  501.     db    ' IOpatch ?   ;Prints these instructions',10,0
  502. Help_Len    equ    *-Help.msg
  503.     quad
  504.  
  505. *****************************************************************************
  506. * NAME
  507. *     SelectWindow - Get the users preference for which unit to open.
  508. *
  509. * SYNOPSIS
  510. *     SelectWindow (UnitExits)
  511. *          D0          D0
  512. *
  513. *     LONG  UnitExists;
  514. *
  515. * INPUTS
  516. *     UnitExists - Non-zero if units 2 and 3 exist, else 0.
  517. *
  518. * RESULTS
  519. *     A value of 0 if the user didn't select a unit and simply hit the close
  520. *     gadget (unit number then defaults to 0).
  521. *
  522. * -> A value of zero is also returned if the user selects the "Internal"
  523. * -> gadget, indicating that he wants to use "serial.device" rather than
  524. * -> "newser.device", or "parallel.device" rather than "eightbit.device".
  525. *
  526. *     A value of 1-4 is returned if the user has selected a unit.
  527. *     A return value of -1 indicates that an error has occured.
  528. *
  529. * NOTES
  530. *     SelectWindow is both relocatable, and reentrant.
  531. *     SelectWindow is Copyright ©1990 by The Puzzle Factory
  532. *
  533. ******************************* tear here ***********************************
  534.  
  535. MyFeatures    equ    SMART_REFRESH!NOCAREREFRESH!ACTIVATE
  536. MyGadgets    equ    WINDOWDRAG!WINDOWDEPTH!WINDOWCLOSE
  537.  
  538. MyBase    clrso        ;BSS structure
  539. Gfx_Base    so.l    1
  540. Int_Base    so.l    1
  541. FontPtr    so.l    1
  542. ScreenPtr    so.l    1
  543. HiresFlag    so.b    1
  544. LaceFlag    so.b    1
  545. MyWindow    so.b    nw_SIZE
  546. Gadget0    so.b    gg_SIZEOF
  547. Gadget1    so.b    gg_SIZEOF
  548. Gadget2    so.b    gg_SIZEOF
  549. Gadget3    so.b    gg_SIZEOF
  550. Gadget4    so.b    gg_SIZEOF
  551.  
  552. Gad0.ITxt    so.b    it_SIZEOF
  553. Gad1.ITxt    so.b    it_SIZEOF
  554. Gad2.ITxt    so.b    it_SIZEOF
  555. Gad3.ITxt    so.b    it_SIZEOF
  556. Gad4.ITxt    so.b    it_SIZEOF
  557. MyBorder    so.b    bd_SIZEOF
  558. MyCoords    so.w    10
  559. Border0    so.b    bd_SIZEOF
  560. Coords0    so.w    10
  561. Text_Attr    so.b    ta_SIZEOF
  562. MB_Sizeof    soval
  563.  
  564. SelWin    move.l    d0,d3    ;UnitExists
  565.     moveq    #0,d7    ;Default = Nothing
  566.     move.l    #MEMF_PUBLIC!MEMF_CLEAR,d1
  567.     move.l    #MB_Sizeof,d0
  568.     movea.l    (SysBase).w,a6
  569.     SYS    AllocMem
  570.     tst.l    d0
  571.     bne.b    1$
  572.     subq.l    #1,d0    ;Return -1 for error
  573.     rts
  574.  
  575. 1$    movea.l    d0,a5    ;Our relative base
  576.     lea    (GfxName,pc),a1    ;Open graphics.library
  577.     moveq    #33,d0
  578.  
  579.     SYS    OpenLibrary
  580.     move.l    d0,(Gfx_Base,a5)
  581.     beq    Error
  582.  
  583.     lea    (IntName,pc),a1    ;Open intuition.library
  584.     moveq    #33,d0
  585.     SYS    OpenLibrary
  586.     move.l    d0,(Int_Base,a5)
  587.     beq    Error
  588.     movea.l    d0,a6
  589.  
  590.     lea    (Text_Attr,a5),a1
  591.     lea    (FontName,pc),a0
  592.     move.l    a0,(ta_Name,a1)
  593.     move.w    #8,(ta_YSize,a1)
  594.     move.b    #FS_NORMAL,(ta_Style,a1)
  595.     move.b    #FPF_ROMFONT,(ta_Flags,a1)
  596.  
  597.     movea.l    (ib_ActiveScreen,a6),a0 ;Get active screen
  598.     move.l    a0,(ScreenPtr,a5)
  599.     move.w    (sc_Width,a0),d0
  600.     cmpi.w    #352,d0    ;Check horz resolution
  601.     sge    (HiresFlag,a5)
  602.     btst    #2,(sc_ViewPort+vp_Modes+1,a0)
  603.     sne    (LaceFlag,a5)
  604.  
  605.     lea    (MyBorder,a5),a1    ;Setup default border
  606.     lea    (Border0,a5),a2
  607.     clr.l    (a1)+    ;bd_LeftEdge,bd_TopEdge
  608.     clr.l    (a2)+    ;bd_LeftEdge,bd_TopEdge
  609.  
  610.     move.l    #$01000005,d0    ;bd_FrontPen,bd_BackPen,bd_DrawMode,bd_Count
  611.     move.l    d0,(a1)+
  612.     move.l    d0,(a2)+
  613.     lea    (MyCoords,a5),a0
  614.     move.l    a0,(a1)+    ;bd_XY
  615.     lea    (Coords0,a5),a0
  616.     move.l    a0,(a2)+    ;bd_XY
  617.  
  618.     lea    (Gadget0,a5),a4
  619.     lea    (Gad0.ITxt,a5),a3
  620.     lea    (GadText.tbl,pc),a2
  621.     tst.b    (HiresFlag,a5)
  622.     bne.b    3$
  623.     lea    (LoresText.tbl,pc),a2
  624. 3$    moveq    #0,d2
  625.  
  626. 4$    lea    (gg_SIZEOF,a4),a0
  627.     move.l    a0,(a4)+    ;gg_NextGadget
  628.  
  629.     moveq    #7,d0    ;0,1,3: LeftEdge=7
  630.     tst.w    d2    ;0
  631.     beq.b    5$
  632.     btst    #0,d2    ;Even or Odd?
  633.     bne.b    5$
  634.     moveq    #55,d0    ;2,4: LeftEdge=55
  635. 5$    tst.b    (HiresFlag,a5)
  636.     beq.b    6$
  637.     add.w    d0,d0
  638. 6$    move.w    d0,(a4)+    ;gg_LeftEdge
  639.  
  640.     moveq    #18,d0    ;0: TopEdge=18
  641.     tst.w    d2
  642.     beq.b    7$
  643.     addi.w    #22,d0    ;1,2: TopEdge=40
  644.     cmpi.w    #3,d2
  645.     blt.b    7$
  646.     addi.w    #22,d0    ;3,4: TopEdge=62
  647. 7$    tst.b    (LaceFlag,a5)
  648.     beq.b    8$
  649.     add.w    d0,d0
  650. 8$    move.w    d0,(a4)+    ;gg_TopEdge
  651.  
  652.     moveq    #40,d0    ;LORES
  653.     tst.w    d2    ;Gadget 0 only
  654.     bne.b    18$
  655.     addq.w    #4,d0
  656.     add.w    d0,d0
  657. 18$    tst.b    (HiresFlag,a5)
  658.     beq.b    9$
  659.     add.w    d0,d0    ;HIRES
  660. 9$    move.w    d0,(a4)+    ;gg_Width
  661.     lea    (MyCoords,a5),a0
  662.     tst.w    d2
  663.     bne.b    19$
  664.     lea    (Coords0,a5),a0    ;Gadget 0 only
  665. 19$    move.w    d0,(4,a0)    ;X border coords
  666.     move.w    d0,(8,a0)
  667.  
  668.     move.w    #18,d0    ;NORMAL
  669.     tst.b    (LaceFlag,a5)
  670.     beq.b    10$
  671.     add.w    d0,d0    ;LACE
  672. 10$    move.w    d0,(a4)+    ;gg_Height
  673.     lea    (MyCoords,a5),a0
  674.     tst.w    d2
  675.     bne.b    20$
  676.     lea    (Coords0,a5),a0    ;Gadget 0 only
  677. 20$    move.w    d0,(10,a0)    ;Y border coords
  678.     move.w    d0,(14,a0)
  679.  
  680.     move.w    #GADGHCOMP,(a4)+    ;gg_Flags
  681.     move.w    #GADGIMMEDIATE,(a4)+ ;gg_Activation
  682.     move.w    #BOOLGADGET,(a4)+    ;gg_GadgetType
  683.     lea    (MyBorder,a5),a0
  684.     tst.w    d2
  685.     bne.b    21$
  686.     lea    (Border0,a5),a0    ;Gadget 0 only
  687. 21$    move.l    a0,(a4)+    ;gg_GadgetRender
  688.     addq.w    #4,a4    ;gg_SelectRender
  689.     move.l    a3,(a4)+    ;gg_GadgetText
  690.     addq.w    #8,a4    ;gg_MutualExclude,gg_SpecialInfo
  691.     move.w    d2,(a4)+    ;gg_GadgetID
  692.     addq.w    #4,a4    ;gg_UserData
  693.  
  694.     move.l    #$01000000,(a3)+    ;it_FrontPen,it_BackPen,it_DrawMode
  695.  
  696.     moveq    #16,d0    ;Gad1-4/HIRES=16
  697.     tst.w    d2
  698.     bne.b    23$
  699.     tst.b    (HiresFlag,a5)    ;Gadget 0 only
  700.     beq.b    22$
  701.     add.w    d0,d0
  702.     add.w    d0,d0    ;Gad0/HIRES=64
  703.     bra.b    11$
  704.  
  705. 22$    addq.w    #4,d0    ;Gad0/LORES=20
  706.     bra.b    11$
  707.  
  708. 23$    tst.b    (HiresFlag,a5)    ;Gadgets 1-4
  709.     bne.b    11$
  710.     subq.w    #4,d0    ;Gad1-4/LORES=12
  711. 11$    move.w    d0,(a3)+    ;it_LeftEdge
  712.  
  713.     moveq    #14,d0
  714.     tst.b    (LaceFlag,a5)
  715.     bne.b    12$
  716.     subq.w    #8,d0
  717. 12$    move.w    d0,(a3)+    ;it_TopEdge
  718.  
  719.     lea    (Text_Attr,a5),a0
  720.     move.l    a0,(a3)+    ;it_TextFont
  721.     move.l    a2,(a3)+    ;it_Text
  722.     addq.w    #4,a3    ;it_NextText
  723.  
  724.     addq.w    #7,a2    ;Next text
  725.     addq.w    #1,d2    ;Next gadget
  726.     cmpi.w    #4,d2    ;All the gadgets done?
  727.     ble.w    4$
  728.  
  729.     clr.l    (Gadget4,a5)    ;gg_NextGadget
  730.  
  731.     lea    (Gadget0,a5),a0
  732.     ori.w    #SELECTED,(gg_Flags,a0)
  733.  
  734.     tst.l    d3    ;Units 2 & 3 exist?
  735.     bne.b    13$    ;Branch if yes
  736.     move.w    #GADGDISABLED,d0    ;Else, disable gadgets
  737.     lea    (Gadget3,a5),a0
  738.     or.w    d0,(gg_Flags,a0)
  739.  
  740.     lea    (Gadget4,a5),a0
  741.     or.w    d0,(gg_Flags,a0)
  742.  
  743. 13$    lea    (MyWindow,a5),a0
  744.     movea.l    (ScreenPtr,a5),a2 ;Get active screen
  745.     move.l    a2,(nw_Screen,a0)    ;
  746.  
  747.     move.w    #103,d0    ;LORES = 103
  748.     tst.b    (HiresFlag,a5)
  749.     beq.b    14$
  750.     add.w    d0,d0    ;HIRES = 206
  751. 14$    move.w    d0,(nw_Width,a0)
  752.     move.w    (sc_Width,a2),d1
  753.     lsr.w    #1,d1    ;Screen width / 2
  754.     lsr.w    #1,d0    ;Window width / 2
  755.     sub.w    d0,d1
  756.     move.w    d1,(a0)    ;nw_LeftEdge
  757.  
  758.     move.w    #88,d0    ;NORMAL = 88
  759.     tst.b    (LaceFlag,a5)
  760.     beq.b    15$
  761.     add.w    d0,d0    ;LACE = 176
  762. 15$    move.w    d0,(nw_Height,a0)
  763.     move.w    (sc_Height,a2),d1
  764.     lsr.w    #1,d1    ;Screen height / 2
  765.     lsr.w    #1,d0    ;Window height / 2
  766.     sub.w    d0,d1
  767.     move.w    d1,(nw_TopEdge,a0)
  768.  
  769.     move.b    #-1,(nw_DetailPen,a0)
  770.     move.b    #-1,(nw_BlockPen,a0)
  771.     move.l    #GADGETDOWN!CLOSEWINDOW,(nw_IDCMPFlags,a0)
  772.     move.l    #MyFeatures!MyGadgets,(nw_Flags,a0)
  773.     lea    (Gadget0,a5),a1
  774.     move.l    a1,(nw_FirstGadget,a0)
  775.     lea    (WindowTitle,pc),a1
  776.     tst.b    (HiresFlag,a5)
  777.     bne.b    16$
  778.     lea    (LoresTitle,pc),a1
  779. 16$    move.l    a1,(nw_Title,a0)
  780.     move.w    (sc_Flags,a2),d0
  781.     andi.w    #%00001111,d0
  782.     move.w    d0,(nw_Type,a0)
  783.     SYS    OpenWindow    ;Open window
  784.     movea.l    d0,a3    ;Save window pointer
  785.     tst.l    d0
  786.     beq.b    Error
  787.  
  788.     movea.l    (Gfx_Base,a5),a6
  789.     lea    (Text_Attr,pc),a0
  790.     SYS    OpenFont
  791.     move.l    d0,(FontPtr,a5)
  792.     beq.b    17$
  793.  
  794.     movea.l    d0,a0
  795.     movea.l    (wd_RPort,a3),a1
  796.     SYS    SetFont
  797.  
  798. 17$    moveq    #0,d6    ;Close flag
  799.     bsr.b    MainLoop
  800.     bra.b    Cleanup
  801.  
  802. ************************************************
  803. *             Termination section              *
  804. ************************************************
  805.  
  806. Error    subq.l    #1,d7
  807. Cleanup    move.l    (Gfx_Base,a5),d2
  808.     beq.b    2$
  809.     move.l    (FontPtr,a5),d0
  810.     beq.b    1$
  811.     movea.l    d0,a1
  812.     movea.l    d2,a6
  813.     SYS    CloseFont
  814.  
  815. 1$    movea.l    d2,a1
  816.     movea.l    (SysBase).w,a6
  817.     SYS    CloseLibrary
  818.  
  819. 2$    move.l    (Int_Base,a5),d2
  820.     beq.b    4$
  821.     move.l    a3,d0
  822.     beq.b    3$
  823.     movea.l d0,a0
  824.     movea.l    d2,a6
  825.     SYS    CloseWindow
  826.  
  827. 3$    movea.l    d2,a1
  828.     movea.l    (SysBase).w,a6
  829.     SYS    CloseLibrary
  830.  
  831. 4$    movea.l    a5,a1
  832.     move.l    #MB_Sizeof,d0
  833.     movea.l    (SysBase).w,a6
  834.     SYS    FreeMem
  835.     move.l    d7,d0    ;0-4, or -1 if error.
  836.     rts
  837.  
  838. ************************************************
  839. *             Main Execution Loop              *
  840. ************************************************
  841.  
  842. MainLoop    tst.w    d6    ;Flag set?
  843.     beq.b    1$
  844.     rts        ;Exit
  845.  
  846. 1$    movea.l (wd_UserPort,a3),a0
  847.     moveq    #0,d0
  848.     moveq    #0,d1
  849.     move.b    (MP_SIGBIT,a0),d1
  850.     bset    d1,d0
  851.     movea.l    (SysBase).w,a6
  852.     SYS    Wait    ;Now wait for a message
  853.  
  854. GetIMsg    movea.l (wd_UserPort,a3),a0
  855.     SYS    GetMsg
  856.     tst.l    d0
  857.     beq.b    MainLoop
  858.     movea.l d0,a1
  859.     move.l    (im_Class,a1),d2
  860.     movea.l    (im_IAddress,a1),a2
  861.     SYS    ReplyMsg
  862.  
  863.     cmpi.l    #CLOSEWINDOW,d2
  864.     bne.b    CheckGads
  865.     moveq    #-1,d6
  866.     bra.b    GetIMsg
  867.  
  868. CheckGads    cmpi.w    #GADGETDOWN,d2    ;Someone clicked on a gadget
  869.     bne.b    1$    ;Unknown class
  870.     moveq    #0,d7
  871.     move.w    (gg_GadgetID,a2),d7 ;ID = Unit number
  872.     lea    (Gadget0,a5),a1    ;1st gadget in group
  873.  
  874.     moveq    #5,d0    ;# of gadgets in group
  875.     bsr.b    MutualExclude
  876. 1$    bra.b    GetIMsg
  877.  
  878. *************************************************************************
  879. * NAME:     MutualExclude()
  880. * FUNCTION: Performs a MutualExclude function for Boolean gadgets.
  881. * INPUTS:   A3 = Window
  882. *           A2 = Currently selected gadget
  883. *           A1 = 1st gadget in group
  884. *           D0 = NumGads
  885. * RETURN:   None
  886. * SCRATCH:  D0-D1/A0-A1
  887. *************************************************************************
  888.  
  889. MutualExclude    move.l    a6,-(sp)
  890.     movea.l    (Int_Base,a5),a6
  891.     movem.l    d0/a1,-(sp)
  892.     movea.l    a3,a0    ;Window
  893.     SYS    RemoveGList
  894.     move.l    d0,d4    ;Position
  895.     movem.l    (sp),d1/a1
  896.     bra.b    3$
  897.  
  898. 1$    cmp.w    (gg_GadgetID,a1),d7 ;Is this the current gadget?
  899.     seq    d2    ;D2 = 1 if TRUE
  900.     btst    #7,(gg_Flags+1,a1)    ;Currently selected?
  901.     sne    d3    ;D3 = 1 if TRUE
  902.     eor.b    d2,d3
  903.     beq.b    2$
  904.     bchg    #7,(gg_Flags+1,a1)    ;Toggle the select flag
  905. 2$    movea.l    (a1),a1    ;gg_NextGadget
  906. 3$    dbra    d1,1$
  907.  
  908.     bsr.b    ClearScreen
  909.  
  910.     movea.l    a3,a0    ;Window
  911.     move.l    d4,d0    ;Position
  912.     movem.l    (sp),d1/a1    ;NumGads/Gadget
  913.     SYS    AddGList
  914.  
  915.     movea.l    a3,a1    ;Window
  916.     movem.l    (sp)+,d0/a0    ;NumGads/Gadget
  917.     SYS    RefreshGList
  918.     movea.l    (sp)+,a6
  919.     rts
  920.  
  921. ClearScreen    movem.l    a2/a6,-(sp)
  922.     movea.l    (Gfx_Base,a5),a6
  923.     movea.l    (wd_RPort,a3),a2
  924.     moveq    #0,d0
  925.     movea.l    a2,a1
  926.     SYS    SetAPen
  927.  
  928.     moveq    #4,d0    ;Xmin
  929.     moveq    #14,d1    ;Ymin
  930.     moveq    #0,d2
  931.     move.w    (wd_Width,a3),d2
  932.     subq.w    #4,d2    ;Xmax
  933.     moveq    #0,d3
  934.     move.w    (wd_Height,a3),d3
  935.     subq.w    #4,d3    ;Ymax
  936.     movea.l    a2,a1
  937.     SYS    RectFill
  938.  
  939.     moveq    #1,d0
  940.     movea.l    a2,a1
  941.     SYS    SetAPen
  942.     movem.l    (sp)+,a2/a6
  943.     rts
  944.  
  945. Notice    cstr    'SelectWindow ©1990 by The Puzzle Factory',10
  946. GfxName    cstr    'graphics.library'
  947. IntName    cstr    'intuition.library'
  948. FontName    cstr    'topaz.font'
  949. WindowTitle    cstr    'Select Unit:'
  950. LoresTitle    cstr    'Sel Unit:'
  951.  
  952. GadText.tbl    cstr    'Unit 0'
  953.     cstr    'Unit 1'
  954.     cstr    'Unit 2'
  955.     cstr    'Unit 3'
  956.     cstr    'Unit 4'
  957.  
  958. LoresText.tbl    cstr    'Unit 0'
  959.     cstr    'U1',0,0,0,0
  960.     cstr    'U2',0,0,0,0
  961.     cstr    'U3',0,0,0,0
  962.     cstr    'U4',0,0,0,0
  963.  
  964. enddispatchcode    end
  965.