home *** CD-ROM | disk | FTP | other *** search
- *\ :ts=8 bk=0
- *
- * BPD.asm: Stands for "Boot PAL, Dammit!" Written as an alternative to
- * all those other programs that attempt to set PAL mode, and
- * never get it right.
- *
- * See, in order for PAL mode to *truly* take effect, you have
- * to convince graphics.library that it's running PAL. To do
- * that, you have to get in before graphics configures itself
- * and set the PAL bit in the ECS agnus. And in order to do
- * *that*, you have to be part of the boot sequence.
- *
- * So this program does precisely that by creating and
- * installing a resident RomTag into the system that survives
- * reboots.
- *
- * Usage: BPD [ '?' | 'REMOVE' | 'NTSC' ]
- *
- * Thanks to Bryce Nesbitt for providing me with an example
- * of how to create resident RomTags.
- *
- * Leo L. Schwab, Silent Software, Inc. 9010.20
- * NTSC hack added (inspired by Nico Francois) 9011.11
- */
- include 'exec/types.i'
- include 'exec/execbase.i'
- include 'exec/resident.i'
- include 'exec/memory.i'
-
- xref _LVOFindResident
- xref _LVOAllocMem
- xref _LVOCopyMem
- xref _LVOSumKickData
- xref _LVODisable
- xref _LVOEnable
- xref _LVOOpenLibrary
- xref _LVOCloseLibrary
-
- xref _LVOOutput
- xref _LVOWrite
-
- xref _vposr ; Custom chip register
-
- TAG_PRI EQU 100 ; Above graphics.library.
-
-
- ****************
- * And we're off!
- *
- SECTION BPD,CODE
- Hello:
- movea.l a0,a3 ; Save argument pointer
- movea.l 4.w,a6 ; ExecBase
- lea dosname(pc),a1
- moveq #0,d0
- jsr _LVOOpenLibrary(a6)
- moveq #20,d2
- move.l d0,d6
- beq openfailed
-
- lea Name(pc),a1
- jsr _LVOFindResident(a6)
-
- * See if ECS Agnus is installed. We check for ID's 0x20 and 0x30. Anything
- * else is considered something we don't know how to deal with.
- *
- move.w _vposr,d1 ; Get ID bits
- andi.w #$3F00,d1 ; Mask off extraneous stuff.
- cmpi.w #$3000,d1 ; Is it NTSC ECS Agnus?
- beq.s 1$
- cmpi.w #$2000,d1 ; Is it PAL ECS Agnus?
- bne notecs
-
- * Scan command line to see what the user wants to do.
- *
- 1$ move.b (a3)+,d1
- cmpi.b #' ',d1
- beq.s 1$ ; Skip past leading blanks.
- cmpi.b #'?',d1 ; Usage line
- beq usage
- cmpi.b #'r',d1 ; Remove
- beq remove
- cmpi.b #'R',d1
- beq remove
- cmpi.b #'n',d1 ; NTSC
- beq.s 2$
- cmpi.b #'N',d1
- bne.s install
-
- * Exceedingly cheap hack to support PAL machines that want to boot into
- * NTSC mode (inspired by Nico Francois' NTSC-PAL programs). This will
- * cause the bootnode to stuff a 0 into the magic ECS Agnus register,
- * which should make the system come up in NTSC mode.
- *
- 2$ clr.w movearg
-
-
- * No meaningful command line arguments supplied, so we'll assume s/he wants
- * to install it.
- *
- install tst.l d0
- bne installed ; Already installed
-
- * Allocate memory to survive reboot.
- *
- move.l #RESIDENT_SIZ,d0
- move.l #MEMF_CHIP!MEMF_PUBLIC,d1
- jsr _LVOAllocMem(a6)
- tst.l d0
- beq nomem
- move.l d0,a2 ; Save pointer
-
- * Relocate pointers to destination.
- *
- lea RelTable(pc),a0
- lea ResStart(pc),a1
- sub.l a1,d0 ; Compute relocation difference
- move.l d0,d7 ; Save it for later
-
- 2$ move.l (a0)+,d0 ; Fetch address of thing to relocate
- beq.s 3$ ; NULL-terminated array
- move.l d0,a1
- add.l d7,(a1) ; Add offset to thing
- bra.s 2$
- 3$:
-
- * Set a few more things atomically.
- *
- jsr _LVODisable(a6)
-
- * Insert MemList into system KickMem list. (I would have used AddHead(),
- * but SysBase.KickMemPtr is not a struct List. Oh well...
- *
- lea MyMemList(pc),a0 ; Address of our memlist
- move.l KickMemPtr(a6),d0
- move.l d0,(a0) ; Append current system entry to us
- add.l d7,a0 ; Add relocation offset
- move.l a0,KickMemPtr(a6) ; Add us to system
-
- * Insert into Resident module list. This is done so that running BPD twice
- * before rebooting will not cause it to be installed twice (that would be
- * bad, you see...).
- *
- lea MyResModule(pc),a0 ; Our ResModule array
- move.l ResModules(a6),d0 ; Already ResModules here?
- beq.s 4$
- bset.l #31,d0 ; Yes, set special indirection flag
- move.l d0,4(a0) ; and store pointer.
- 4$:
- add.l d7,a0 ; Add relocation offset
- move.l a0,ResModules(a6) ; Insert us into Exec list
-
- * Insert into KickTagPtr list.
- *
- lea MyKickTagPtr(pc),a0 ; Our KickTagPtr array
- move.l KickTagPtr(a6),d0 ; Already KickTagPtrs here?
- beq.s 5$
- bset.l #31,d0 ; Yep...
- move.l d0,4(a0)
- 5$:
- add.l d7,a0 ; Relocate...
- move.l a0,KickTagPtr(a6) ; Insert us into Exec list
-
- * Copy resident code and data into allocated memory.
- *
- lea ResStart(pc),a0 ; src
- movea.l a2,a1 ; dest
- move.l #RESIDENT_SIZ,d0
- jsr _LVOCopyMem(a6)
-
- * Recompute KickCheckSum.
- *
- jsr _LVOSumKickData(a6)
- move.l d0,KickCheckSum(a6)
-
- * Return to reality.
- *
- jsr _LVOEnable(a6)
- lea BPD.msg(pc),a2
- bsr climsg
- lea installed.msg(pc),a2
- bsr climsg
-
- exit lea change.msg(pc),a2
- bsr climsg
- eexit movea.l d6,a1
- jsr _LVOCloseLibrary(a6)
- openfailed move.l d2,d0 ; D2 usually set to 0 by climsg
- rts
-
- errexit moveq #20,d2
- bra.s eexit
-
-
- ****************
- * User wants to remove the goodie.
- *
- remove tst.l d0
- beq.s nothere ; Nothing to remove
-
- * Remove ourselves from the system lists. First the KickMemPtr list.
- *
- lea KickMemPtr(a6),a1
- 1$ movea.l a1,a0
- move.l (a0),d1
- beq.s nothere ; Couldn't find MemList entry.
-
- movea.l d1,a1
- cmp.l ML_ME+ME_ADDR(a1),d0 ; See if it's us.
- bne.s 1$
-
- move.l (a1),(a0) ; Pull us from the list.
-
- * Now try to find us in the KickTagPtr list.
- *
- lea KickTagPtr(a6),a0
- tablehop move.l (a0),d1
- beq.s nothere ; End of tables; Couldn't find us.
- bclr.l #31,d1
- movea.l d1,a1
-
- tableloop move.l (a1)+,d1
- bgt.s 2$
- lea -4(a1),a0 ; Indirection, get pointer to it
- bra.s tablehop ; and loop to next table
-
- 2$ cmp.l d1,d0 ; Is it us?
- bne.s tableloop
-
- * We found ourselves. Now perform remove. (Since I know the format of
- * the table I installed, I can make assumptions about the data I'm zapping.)
- *
- move.l (a1),d1 ; Get pointer to next table.
- btst.b #7,(a0) ; Did we get here by indirection?
- bne.s 3$
- bclr.l #31,d1 ; No, clear indirection bit.
- 3$ move.l d1,(a0) ; Patch to jumper over us.
-
- * Reset KickCheckSum.
- *
- jsr _LVOSumKickData(a6)
- move.l d0,KickCheckSum(a6)
-
- lea BPD.msg(pc),a2
- bsr.s climsg
- lea removed.msg(pc),a2
- bsr.s climsg
- bra.s exit
-
-
- ****************
- * Diagnostic messages.
- *
- installed lea BPD.msg(pc),a2
- bsr.s climsg
- lea already.msg(pc),a2
- bsr.s climsg
- bra.s errexit
-
- nomem lea nomem.msg(pc),a2
- bsr.s climsg
- bra.s errexit
-
- notecs lea notecs.msg(pc),a2
- bsr.s climsg
- bra.s errexit
-
- nothere lea BPD.msg(pc),a2
- bsr.s climsg
- lea not.msg(pc),a2
- bsr.s climsg
- lea installed.msg(pc),a2
- bsr.s climsg
- bra errexit
-
- usage lea ID(pc),a2
- bsr.s climsg
- lea usage.msg(pc),a2
- bsr.s climsg
- bra exit
-
- ****************
- * Routine to print to CLI.
- *
- climsg exg d6,a6 ; Error string pointer in A2
- jsr _LVOOutput(a6)
- move.l d0,d1
- beq.s noout ; No output channel
-
- move.l a2,d2 ; Compute string length
- 1$ tst.b (a2)+
- bne.s 1$
- suba.l d2,a2
- move.l a2,d3
- subq.l #1,d3
- jsr _LVOWrite(a6) ; Write string
- noout exg d6,a6
- moveq #0,d2
- rts
-
-
- ****************
- * Relocation table. Contains pointers to addresses to be moved.
- *
- RelTable dc.l RL0,RL1,RL2,RL3,RL4,RL5,RL6,RL7,RL8,0
-
- * Diagnostic strings.
- *
- dosname dc.b 'dos.library',0
- BPD.msg dc.b 'BPD ',0
- already.msg dc.b 'already '
- installed.msg dc.b 'installed.',10,0
- not.msg dc.b 'not ',0
- notecs.msg dc.b 'ECS Agnus not present.',10,0
- nomem.msg dc.b 'No memory for resident RomTag.',10,0
- removed.msg dc.b 'removed.',10,0
- usage.msg dc.b 'This program may be freely distributed.',10,10
- dc.b 'Usage: BPD [REMOVE | NTSC]',10,0
- change.msg dc.b 'Change will take effect on next reboot.',10,0
-
-
- ************************************************************************
- * The resident stuff intended to survive reboot.
- *
- ResStart: cnop 0,2
-
- * The Resident structure.
- *
- RomTag: ;STRUCTURE RT,0
- dc.w RTC_MATCHWORD ; UWORD RT_MATCHWORD
- RL0: dc.l RomTag ; APTR RT_MATCHTAG
- RL1: dc.l ResEnd ; APTR RT_ENDSKIP
- dc.b RTF_COLDSTART ; UBYTE RT_FLAGS
- dc.b 1 ; UBYTE RT_VERSION
- dc.b NT_BOOTNODE ; UBYTE RT_TYPE
- dc.b TAG_PRI ; BYTE RT_PRI
- RL2: dc.l Name ; APTR RT_NAME
- RL3: dc.l ID ; APTR RT_IDSTRING
- RL4: dc.l PALTrick ; APTR RT_INIT
-
-
- * The MemList.
- *
- MyMemList: ; STRUCTURE ML,LN_SIZE
- ; STRUCTURE LN,0
- dc.l 0 ; APTR LN_SUCC
- dc.l 0 ; APTR LN_PRED
- dc.b NT_MEMORY ; UBYTE LN_TYPE
- dc.b 0 ; BYTE LN_PRI
- RL5: dc.l Name ; APTR LN_NAME
- dc.w 1 ; UWORD ML_NUMENTRIES
- ; STRUCTURE ME,0
- RL6: dc.l ResStart ; APTR ME_ADDR
- dc.l RESIDENT_SIZ ; ULONG ME_LENGTH
-
-
- * Array of pointers to RomTag structures describing things to be made
- * resident. If the entry in the array has bit 31 set (0x80000000), then
- * the pointer (sans high bit) is in fact a pointer to *another* array of
- * RomTag pointers. A NULL terminates the array.
- * (These also need relocation.)
- *
- RL7:
- MyKickTagPtr dc.l RomTag,0
- RL8:
- MyResModule dc.l RomTag,0
-
-
- * Name and ID strings. (I wonder if Xoper will show these?)
- *
- Name dc.b 'BPD.resident',0
- ID dc.b 'BPD (Boot PAL, Dammit!) v1.1 by Leo L. Schwab '
- dc.b '(11 Nov 1990)',13,10,0
-
- ****************
- * Why we went to all this trouble. Kind of anti-climactic, isn't it?
- * (PAL Now Brown Cow)
- *
- PALTrick: btst.b #6,$BFE001 ; Check mouse button
- beq.s palexit ; If pressed, let user boot normally
-
- movearg EQU *+2 ; The immediate argument to the
- MOVE
- move.w #$0020,$DFF1DC ; Turn on PAL bit in ECS Agnus
- palexit: moveq #0,d0
- rts
-
- ResEnd EQU *
- RESIDENT_SIZ EQU ResEnd-ResStart ; Size of preserved block.
-
- END
-