home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Club Amiga de Montreal - CAM
/
CAM_CD_1.iso
/
files
/
455.lha
/
BPD
/
BPD.asm
< prev
next >
Wrap
Assembly Source File
|
1990-12-10
|
10KB
|
391 lines
*\ :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