home *** CD-ROM | disk | FTP | other *** search
/ The CDPD Public Domain Collection for CDTV 3 / CDPDIII.bin / pd / programming / assembler / thesource / volume1 / source / system / bpd.lha / BPD.asm next >
Encoding:
Assembly Source File  |  1991-03-15  |  13.2 KB  |  392 lines

  1. *\  :ts=8 bk=0
  2. *
  3. * BPD.asm:     Stands for "Boot PAL, Dammit!"  Written as an alternative to
  4. *              all those other programs that attempt to set PAL mode, and
  5. *              never get it right.
  6. *
  7. *              See, in order for PAL mode to *truly* take effect, you have
  8. *              to convince graphics.library that it's running PAL.  To do
  9. *              that, you have to get in before graphics configures itself
  10. *              and set the PAL bit in the ECS agnus.  And in order to do
  11. *              *that*, you have to be part of the boot sequence.
  12. *
  13. *              So this program does precisely that by creating and
  14. *              installing a resident RomTag into the system that survives
  15. *              reboots.
  16. *
  17. *              Usage:  BPD [ '?' | 'REMOVE' | 'NTSC' ]
  18. *
  19. *              Thanks to Bryce Nesbitt for providing me with an example
  20. *              of how to create resident RomTags.
  21. *
  22. * Leo L. Schwab,  Silent Software, Inc.                        9010.20
  23. * NTSC hack added (inspired by Nico Francois)          9011.11
  24. */
  25.                include 'exec/types.i'
  26.                include 'exec/execbase.i'
  27.                include 'exec/resident.i'
  28.                include 'exec/memory.i'
  29.  
  30.                xref    _LVOFindResident
  31.                xref    _LVOAllocMem
  32.                xref    _LVOCopyMem
  33.                xref    _LVOSumKickData
  34.                xref    _LVODisable
  35.                xref    _LVOEnable
  36.                xref    _LVOOpenLibrary
  37.                xref    _LVOCloseLibrary
  38.  
  39.                xref    _LVOOutput
  40.                xref    _LVOWrite
  41.  
  42.                xref    _vposr          ; Custom chip register
  43.  
  44. TAG_PRI                EQU     100             ; Above graphics.library.
  45.  
  46.  
  47. ****************
  48. * And we're off!
  49. *
  50.                SECTION BPD,CODE
  51. Hello:
  52.                movea.l a0,a3           ; Save argument pointer
  53.                movea.l 4.w,a6          ; ExecBase
  54.                lea     dosname(pc),a1
  55.                moveq   #0,d0
  56.                jsr     _LVOOpenLibrary(a6)
  57.                moveq   #20,d2
  58.                move.l  d0,d6
  59.                beq     openfailed
  60.  
  61.                lea     Name(pc),a1
  62.                jsr     _LVOFindResident(a6)
  63.  
  64. * See if ECS Agnus is installed.  We check for ID's 0x20 and 0x30.  Anything
  65. * else is considered something we don't know how to deal with.
  66. *
  67.                move.w  _vposr,d1       ; Get ID bits
  68.                andi.w  #$3F00,d1       ; Mask off extraneous stuff.
  69.                cmpi.w  #$3000,d1       ; Is it NTSC ECS Agnus?
  70.                beq.s   1$
  71.                cmpi.w  #$2000,d1       ; Is it PAL ECS Agnus?
  72.                bne     notecs
  73.  
  74. * Scan command line to see what the user wants to do.
  75. *
  76. 1$             move.b  (a3)+,d1
  77.                cmpi.b  #' ',d1
  78.                beq.s   1$              ; Skip past leading blanks.
  79.                cmpi.b  #'?',d1         ; Usage line
  80.                beq     usage
  81.                cmpi.b  #'r',d1         ; Remove
  82.                beq     remove
  83.                cmpi.b  #'R',d1
  84.                beq     remove
  85.                cmpi.b  #'n',d1         ; NTSC
  86.                beq.s   2$
  87.                cmpi.b  #'N',d1
  88.                bne.s   install
  89.  
  90. * Exceedingly cheap hack to support PAL machines that want to boot into
  91. * NTSC mode (inspired by Nico Francois' NTSC-PAL programs).  This will
  92. * cause the bootnode to stuff a 0 into the magic ECS Agnus register,
  93. * which should make the system come up in NTSC mode.
  94. *
  95. 2$             clr.w   movearg
  96.  
  97.  
  98. * No meaningful command line arguments supplied, so we'll assume s/he wants
  99. * to install it.
  100. *
  101. install                tst.l   d0
  102.                bne     installed       ; Already installed
  103.  
  104. * Allocate memory to survive reboot.
  105. *
  106.                move.l  #RESIDENT_SIZ,d0
  107.                move.l  #MEMF_CHIP!MEMF_PUBLIC,d1
  108.                jsr     _LVOAllocMem(a6)
  109.                tst.l   d0
  110.                beq     nomem
  111.                move.l  d0,a2           ; Save pointer
  112.  
  113. * Relocate pointers to destination.
  114. *
  115.                lea     RelTable(pc),a0
  116.                lea     ResStart(pc),a1
  117.                sub.l   a1,d0           ; Compute relocation difference
  118.                move.l  d0,d7           ; Save it for later
  119.  
  120. 2$             move.l  (a0)+,d0        ; Fetch address of thing to relocate
  121.                beq.s   3$              ; NULL-terminated array
  122.                move.l  d0,a1
  123.                add.l   d7,(a1)         ; Add offset to thing
  124.                bra.s   2$
  125. 3$:
  126.  
  127. * Set a few more things atomically.
  128. *
  129.                jsr     _LVODisable(a6)
  130.  
  131. * Insert MemList into system KickMem list.  (I would have used AddHead(),
  132. * but SysBase.KickMemPtr is not a struct List.  Oh well...
  133. *
  134.                lea     MyMemList(pc),a0        ; Address of our memlist
  135.                move.l  KickMemPtr(a6),d0
  136.                move.l  d0,(a0)         ; Append current system entry to us
  137.                add.l   d7,a0           ; Add relocation offset
  138.                move.l  a0,KickMemPtr(a6)       ; Add us to system
  139.  
  140. * Insert into Resident module list.  This is done so that running BPD twice
  141. * before rebooting will not cause it to be installed twice (that would be
  142. * bad, you see...).
  143. *
  144.                lea     MyResModule(pc),a0      ; Our ResModule array
  145.                move.l  ResModules(a6),d0       ; Already ResModules here?
  146.                beq.s   4$
  147.                bset.l  #31,d0          ; Yes, set special indirection flag
  148.                move.l  d0,4(a0)        ;  and store pointer.
  149. 4$:
  150.                add.l   d7,a0           ; Add relocation offset
  151.                move.l  a0,ResModules(a6)       ; Insert us into Exec list
  152.  
  153. * Insert into KickTagPtr list.
  154. *
  155.                lea     MyKickTagPtr(pc),a0     ; Our KickTagPtr array
  156.                move.l  KickTagPtr(a6),d0       ; Already KickTagPtrs here?
  157.                beq.s   5$
  158.                bset.l  #31,d0          ; Yep...
  159.                move.l  d0,4(a0)
  160. 5$:
  161.                add.l   d7,a0           ; Relocate...
  162.                move.l  a0,KickTagPtr(a6)       ; Insert us into Exec list
  163.  
  164. * Copy resident code and data into allocated memory.
  165. *
  166.                lea     ResStart(pc),a0 ; src
  167.                movea.l a2,a1           ; dest
  168.                move.l  #RESIDENT_SIZ,d0
  169.                jsr     _LVOCopyMem(a6)
  170.  
  171. * Recompute KickCheckSum.
  172. *
  173.                jsr     _LVOSumKickData(a6)
  174.                move.l  d0,KickCheckSum(a6)
  175.  
  176. * Return to reality.
  177. *
  178.                jsr     _LVOEnable(a6)
  179.                lea     BPD.msg(pc),a2
  180.                bsr     climsg
  181.                lea     installed.msg(pc),a2
  182.                bsr     climsg
  183.  
  184. exit           lea     change.msg(pc),a2
  185.                bsr     climsg
  186. eexit          movea.l d6,a1
  187.                jsr     _LVOCloseLibrary(a6)
  188. openfailed     move.l  d2,d0           ; D2 usually set to 0 by climsg
  189.                rts
  190.  
  191. errexit                moveq   #20,d2
  192.                bra.s   eexit
  193.  
  194.  
  195. ****************
  196. * User wants to remove the goodie.
  197. *
  198. remove         tst.l   d0
  199.                beq.s   nothere         ; Nothing to remove
  200.  
  201. * Remove ourselves from the system lists.  First the KickMemPtr list.
  202. *
  203.                lea     KickMemPtr(a6),a1
  204. 1$             movea.l a1,a0
  205.                move.l  (a0),d1
  206.                beq.s   nothere         ; Couldn't find MemList entry.
  207.  
  208.                movea.l d1,a1
  209.                cmp.l   ML_ME+ME_ADDR(a1),d0    ; See if it's us.
  210.                bne.s   1$
  211.  
  212.                move.l  (a1),(a0)       ; Pull us from the list.
  213.  
  214. * Now try to find us in the KickTagPtr list.
  215. *
  216.                lea     KickTagPtr(a6),a0
  217. tablehop       move.l  (a0),d1
  218.                beq.s   nothere         ; End of tables;  Couldn't find us.
  219.                bclr.l  #31,d1
  220.                movea.l d1,a1
  221.  
  222. tableloop      move.l  (a1)+,d1
  223.                bgt.s   2$
  224.                lea     -4(a1),a0       ; Indirection, get pointer to it
  225.                bra.s   tablehop        ;  and loop to next table
  226.  
  227. 2$             cmp.l   d1,d0           ; Is it us?
  228.                bne.s   tableloop
  229.  
  230. * We found ourselves.  Now perform remove.  (Since I know the format of
  231. * the table I installed, I can make assumptions about the data I'm zapping.)
  232. *
  233.                move.l  (a1),d1         ; Get pointer to next table.
  234.                btst.b  #7,(a0)         ; Did we get here by indirection?
  235.                bne.s   3$
  236.                bclr.l  #31,d1          ; No, clear indirection bit.
  237. 3$             move.l  d1,(a0)         ; Patch to jumper over us.
  238.  
  239. * Reset KickCheckSum.
  240. *
  241.                jsr     _LVOSumKickData(a6)
  242.                move.l  d0,KickCheckSum(a6)
  243.  
  244.                lea     BPD.msg(pc),a2
  245.                bsr.s   climsg
  246.                lea     removed.msg(pc),a2
  247.                bsr.s   climsg
  248.                bra.s   exit
  249.  
  250.  
  251. ****************
  252. * Diagnostic messages.
  253. *
  254. installed      lea     BPD.msg(pc),a2
  255.                bsr.s   climsg
  256.                lea     already.msg(pc),a2
  257.                bsr.s   climsg
  258.                bra.s   errexit
  259.  
  260. nomem          lea     nomem.msg(pc),a2
  261.                bsr.s   climsg
  262.                bra.s   errexit
  263.  
  264. notecs         lea     notecs.msg(pc),a2
  265.                bsr.s   climsg
  266.                bra.s   errexit
  267.  
  268. nothere                lea     BPD.msg(pc),a2
  269.                bsr.s   climsg
  270.                lea     not.msg(pc),a2
  271.                bsr.s   climsg
  272.                lea     installed.msg(pc),a2
  273.                bsr.s   climsg
  274.                bra     errexit
  275.  
  276. usage          lea     ID(pc),a2
  277.                bsr.s   climsg
  278.                lea     usage.msg(pc),a2
  279.                bsr.s   climsg
  280.                bra     exit
  281.  
  282. ****************
  283. * Routine to print to CLI.
  284. *
  285. climsg         exg     d6,a6           ; Error string pointer in A2
  286.                jsr     _LVOOutput(a6)
  287.                move.l  d0,d1
  288.                beq.s   noout           ; No output channel
  289.  
  290.                move.l  a2,d2           ; Compute string length
  291. 1$             tst.b   (a2)+
  292.                bne.s   1$
  293.                suba.l  d2,a2
  294.                move.l  a2,d3
  295.                subq.l  #1,d3
  296.                jsr     _LVOWrite(a6)   ; Write string
  297. noout          exg     d6,a6
  298.                moveq   #0,d2
  299.                rts
  300.  
  301.  
  302. ****************
  303. * Relocation table.  Contains pointers to addresses to be moved.
  304. *
  305. RelTable       dc.l    RL0,RL1,RL2,RL3,RL4,RL5,RL6,RL7,RL8,0
  306.  
  307. * Diagnostic strings.
  308. *
  309. dosname                dc.b    'dos.library',0
  310. BPD.msg                dc.b    'BPD ',0
  311. already.msg    dc.b    'already '
  312. installed.msg  dc.b    'installed.',10,0
  313. not.msg                dc.b    'not ',0
  314. notecs.msg     dc.b    'ECS Agnus not present.',10,0
  315. nomem.msg      dc.b    'No memory for resident RomTag.',10,0
  316. removed.msg    dc.b    'removed.',10,0
  317. usage.msg      dc.b    'This program may be freely distributed.',10,10
  318.                dc.b    'Usage: BPD [REMOVE | NTSC]',10,0
  319. change.msg     dc.b    'Change will take effect on next reboot.',10,0
  320.  
  321.  
  322. ************************************************************************
  323. * The resident stuff intended to survive reboot.
  324. *
  325. ResStart:      cnop    0,2
  326.  
  327. * The Resident structure.
  328. *
  329. RomTag:                                        ;STRUCTURE RT,0
  330.                dc.w    RTC_MATCHWORD   ;   UWORD RT_MATCHWORD
  331. RL0:           dc.l    RomTag          ;   APTR  RT_MATCHTAG
  332. RL1:           dc.l    ResEnd          ;   APTR  RT_ENDSKIP
  333.                dc.b    RTF_COLDSTART   ;   UBYTE RT_FLAGS
  334.                dc.b    1               ;   UBYTE RT_VERSION
  335.                dc.b    NT_BOOTNODE     ;   UBYTE RT_TYPE
  336.                dc.b    TAG_PRI         ;   BYTE  RT_PRI
  337. RL2:           dc.l    Name            ;   APTR  RT_NAME
  338. RL3:           dc.l    ID              ;   APTR  RT_IDSTRING
  339. RL4:           dc.l    PALTrick        ;   APTR  RT_INIT
  340.  
  341.  
  342. * The MemList.
  343. *
  344. MyMemList:                             ; STRUCTURE ML,LN_SIZE
  345.                                        ;       STRUCTURE  LN,0
  346.                dc.l    0               ;          APTR    LN_SUCC
  347.                dc.l    0               ;          APTR    LN_PRED
  348.                dc.b    NT_MEMORY       ;          UBYTE   LN_TYPE
  349.                dc.b    0               ;          BYTE    LN_PRI
  350. RL5:           dc.l    Name            ;          APTR    LN_NAME
  351.                dc.w    1               ;    UWORD   ML_NUMENTRIES
  352.                                        ; STRUCTURE ME,0
  353. RL6:           dc.l    ResStart        ;    APTR    ME_ADDR
  354.                dc.l    RESIDENT_SIZ    ;    ULONG   ME_LENGTH
  355.  
  356.  
  357. * Array of pointers to RomTag structures describing things to be made
  358. * resident.  If the entry in the array has bit 31 set (0x80000000), then
  359. * the pointer (sans high bit) is in fact a pointer to *another* array of
  360. * RomTag pointers.  A NULL terminates the array.
  361. * (These also need relocation.)
  362. *
  363. RL7:
  364. MyKickTagPtr   dc.l    RomTag,0
  365. RL8:
  366. MyResModule    dc.l    RomTag,0
  367.  
  368.  
  369. * Name and ID strings.  (I wonder if Xoper will show these?)
  370. *
  371. Name           dc.b    'BPD.resident',0
  372. ID             dc.b    'BPD (Boot PAL, Dammit!) v1.1 by Leo L. Schwab  '
  373.                dc.b    '(11 Nov 1990)',13,10,0
  374.  
  375. ****************
  376. * Why we went to all this trouble.  Kind of anti-climactic, isn't it?
  377. * (PAL Now Brown Cow)
  378. *
  379. PALTrick:      btst.b  #6,$BFE001      ; Check mouse button
  380.                beq.s   palexit         ; If pressed, let user boot normally
  381.  
  382. movearg                EQU     *+2             ; The immediate argument to the
  383. MOVE
  384.                move.w  #$0020,$DFF1DC  ; Turn on PAL bit in ECS Agnus
  385. palexit:       moveq   #0,d0
  386.                rts
  387.  
  388. ResEnd         EQU     *
  389. RESIDENT_SIZ   EQU     ResEnd-ResStart ; Size of preserved block.
  390.  
  391.                END
  392.