mirror of
https://github.com/elliotnunn/NetBoot.git
synced 2024-12-26 10:32:12 +00:00
340 lines
8.4 KiB
Plaintext
340 lines
8.4 KiB
Plaintext
; Input appended to this code:
|
|
; [4 arbitrary bytes] [byte-prefixed pstring] [padding to even byte] ... [4 bytes] [zero byte]
|
|
|
|
; Outputs: D0 = index of selected string, Ao = pointer to selected string
|
|
|
|
_BoundaryLabelAtStartOfBootPicker_
|
|
|
|
; Aesthetic parameters
|
|
.kMinWid equ 70 ; min width to leave for button label
|
|
.kBtnHt equ 20 ; should always be 20 because text won't move
|
|
.kBtnGap equ 13
|
|
.kPadX equ 5+26 ; due to border, padding=6 would leave 1 white pixel
|
|
.kPadY equ 5+13
|
|
|
|
|
|
; Save all the stuff that we whack
|
|
movem.l A1-A5/D1-D7,-(SP)
|
|
move.l $3F8,-(SP) ; Save DSAlertRect
|
|
move.l $3F8+4,-(SP)
|
|
move.l $9CE,-(SP) ; Save ToolScratch
|
|
move.l $9CE+4,-(SP)
|
|
move.l $2BA,-(SP) ; Save DSAlertTab
|
|
move.l $A8C,-(SP) ; Save RestProc
|
|
move.l $120,-(SP) ; Save MacJmp
|
|
move.b $BFF,-(SP) ; Save MacJmpFlag (32-bit only)
|
|
link.w A6,#0 ; We use a lot of stack
|
|
|
|
|
|
; Head-patch _PtInRect to account for our unusual window placement
|
|
move.w #$A8AD,D0 ; _PtInRect
|
|
dc.w $A146 ; _GetTrapAddress
|
|
move.l A0,$9CE+4 ; Save in ToolScratch+4 to enable head-patch
|
|
|
|
move.w #$A8AD,D0 ; _PtInRect
|
|
lea .MyPtInRect,A0
|
|
dc.w $A047 ; _SetTrapAddress
|
|
|
|
|
|
; Do the usual "QuickDraw outside of application" setup
|
|
clr.l -(SP)
|
|
move.l SP,A5 ; tiny A5 world with QD globals ptr
|
|
lea -206(SP),SP ; push the QD globals
|
|
pea 202(SP)
|
|
dc.w $A86E ; _InitGraf
|
|
dc.w $A8FE ; _InitFonts (because we use _StringWidth)
|
|
lea -108(SP),SP
|
|
pea (SP)
|
|
dc.w $A86F ; _OpenPort (don't save, we have our own globs)
|
|
|
|
|
|
; Copy a stub alert table to the stack
|
|
move.l #.MyDSAlertTabEnd-.MyDSAlertTabStart,D0
|
|
sub.l D0,SP
|
|
move.l SP,A1
|
|
lea .MyDSAlertTabStart,A0
|
|
dc.w $A22E ; _BlockMoveData
|
|
|
|
|
|
; First pass: calculate box width, putting shortest string width into D5
|
|
moveq.l #.kMinWid,D5
|
|
bsr .GetA0 ; A0 = current pstring ptr
|
|
.dswLoop
|
|
tst.b (A0)
|
|
beq.s .dswDone
|
|
|
|
move.l A0,-(SP)
|
|
clr.w -(SP)
|
|
move.l A0,-(SP)
|
|
dc.w $A88C ; _StringWidth
|
|
move.w (SP)+,D0
|
|
addq.w #8,D0
|
|
cmp.w D0,D5
|
|
bgt.s .notlargest
|
|
move.w D0,D5
|
|
.notlargest
|
|
move.l (SP)+,A0
|
|
|
|
bsr .AdvanceA0
|
|
bra.s .dswLoop
|
|
.dswDone
|
|
|
|
|
|
; Second pass: create a button list object in the DS alert table
|
|
move.w (SP)+,D7 ; pop NumEntries from DS table
|
|
|
|
move.l #((.kPadY)<<16)|(.kPadX),D2 ; D2 = current button's topleft
|
|
move.l #((.kPadY+.kBtnHt)<<16)|(.kPadX+4+4),D3; D3 = current button's botright
|
|
add.w D5,D3 ; ...including width of the text
|
|
moveq.l #0,D6 ; D6 = button counter
|
|
bsr .GetA0 ; A0 = current pstring ptr
|
|
.dsbLoop
|
|
tst.b (A0)
|
|
beq.s .dsbDone
|
|
|
|
move.w D6,-(SP) ; push procedure object ID (base $8000)
|
|
add.w #$8000,(SP)
|
|
move.l D3,-(SP) ; push botright
|
|
move.l D2,-(SP) ; push topleft
|
|
move.w D6,-(SP) ; push string object ID (base $C000)
|
|
add.w #$C000,(SP)
|
|
; increment...
|
|
add.l #(.kBtnHt+.kBtnGap)<<16,D2 ; the button's top edge
|
|
add.l #(.kBtnHt+.kBtnGap)<<16,D3 ; the button's bottom edge
|
|
addq.w #1,D6 ; the button counter
|
|
bsr .AdvanceA0
|
|
bra.s .dsbLoop
|
|
|
|
.dsbDone ; done looping, push a header for this object...
|
|
move.w D6,-(SP) ; the number of buttons
|
|
mulu #12,D6 ; the size in bytes = 12n+2
|
|
add.w #2,D6
|
|
move.w D6,-(SP)
|
|
move.w #$1993,-(SP) ; the unique ID for this button list
|
|
|
|
addq.w #1,D7
|
|
move.w D7,-(SP) ; increment and re-push NumEntries
|
|
|
|
|
|
; Third pass: calculate box height
|
|
lea $3F8,A1 ; A0 = DSAlertRect
|
|
move.l (A5),A0 ; From QD globals
|
|
move.l -122+6+4(A0),D0 ; D0 = screenBits.bounds.botRight, so D0.W = screen width
|
|
|
|
add.w #.kPadX,D3 ; D3 = box width
|
|
sub.w D3,D0
|
|
bgt.s .nottoowide
|
|
clr.w D0
|
|
.nottoowide
|
|
asr.w #1,D0
|
|
move.w D0,2(A1) ; set DSAlertRect left
|
|
move.w D0,$9CE+2 ; & stash in ToolScratch for .MyPtInRect
|
|
add.w D3,D0
|
|
move.w D0,6(A1) ; set DSAlertRect right
|
|
|
|
swap D0 ; D0 = screen height
|
|
swap D2 ; D2 = box height ("top" of next button)
|
|
add.w #.kPadY-.kBtnGap,D2 ; adjust box height
|
|
sub.w D2,D0
|
|
bgt.s .nottoohigh
|
|
clr.w D0
|
|
.nottoohigh
|
|
asr.w #1,D0
|
|
move.w D0,(A1) ; set DSAlertRect top
|
|
move.w D0,$9CE ; & stash in ToolScratch for .MyPtInRect
|
|
add.w D2,D0
|
|
move.w D0,4(A1) ; set DSAlertRect bottom
|
|
|
|
|
|
; Fourth pass: create a string offset for each button
|
|
moveq.l #0,D6 ; D6 = button counter
|
|
bsr .GetA0 ; A0 = current pstring ptr
|
|
.dssLoop
|
|
tst.b (A0)
|
|
beq.s .dssDone
|
|
|
|
move.w (SP)+,D7 ; pop NumEntries from DS table
|
|
|
|
; push the struct fields...
|
|
bsr .PushPaddedString ; even-length string with 2-byte length
|
|
move.w D6,-(SP) ; the unique ID (C000+n)
|
|
add.w #$C000,(SP)
|
|
|
|
addq.w #1,D7
|
|
move.w D7,-(SP) ; increment and re-push NumEntries
|
|
|
|
; increment...
|
|
addq.w #1,D6 ; the button counter
|
|
bsr .AdvanceA0
|
|
bra.s .dssLoop
|
|
.dssDone
|
|
|
|
|
|
; Fifth pass: generate code for each button
|
|
moveq.l #0,D6 ; D6 = button counter
|
|
bsr .GetA0 ; A0 = current pstring ptr
|
|
.dspLoop
|
|
tst.b (A0)
|
|
beq.s .dspDone
|
|
|
|
move.w (SP)+,D7 ; pop NumEntries from DS table
|
|
|
|
pea .ReturnToCaller ; craft the code for this button...
|
|
move.w #$4EF9,-(SP) ; jmp .ReturnToCaller (absolute addr)
|
|
move.l A6,-(SP)
|
|
move.w #$2C7C,-(SP) ; move.l #CorrectA6,A6 ; frame ptr
|
|
move.l A0,-(SP)
|
|
move.w #$207C,-(SP) ; move.l #CorrectA0,A0 ; return string ptr
|
|
move.l D6,-(SP)
|
|
move.w #$203C,-(SP) ; move.l #CorrectD0,D0 ; return string idx
|
|
|
|
; push a header...
|
|
move.w #24,-(SP) ; the size in bytes of the above code
|
|
move.w D6,-(SP) ; the unique ID (8000+n)
|
|
add.w #$8000,(SP)
|
|
|
|
addq.w #1,D7
|
|
move.w D7,-(SP) ; increment and re-push NumEntries
|
|
|
|
; increment...
|
|
addq.w #1,D6 ; the button counter
|
|
bsr .AdvanceA0
|
|
bra.s .dspLoop
|
|
|
|
.dspDone ; Must clear the instruction cache on 030/040
|
|
move.l A6,D0
|
|
sub.l SP,D0
|
|
move.l SP,A0
|
|
move.l SP,A1
|
|
dc.w $A02E ; using non-Data _BlockMove
|
|
|
|
|
|
; Put up the DeepShit alert
|
|
move.l SP,$2BA ; Set DSAlertTab
|
|
clr.l $A8C ; Clear RestProc or our buttons get jumbled
|
|
move.w #$2012,D0 ; Our error object number
|
|
dc.w $A9C9 ; _SysError!
|
|
bra.s * ; Should never return
|
|
|
|
|
|
; The selected procedure will jump to here after setting A6,A0,D0
|
|
.ReturnToCaller
|
|
movem.l A0/D0,-(SP) ; save/restore our return values
|
|
|
|
move.l (A5),A0 ; Open a new whole-screen port
|
|
move.l (A0),-(SP)
|
|
dc.w $A86F ; _OpenPort
|
|
|
|
pea $3F8 ; DSAlertRect
|
|
move.l (A5),A0 ;
|
|
pea -24(A0) ; qd.gray
|
|
dc.w $A8A5 ; _FillRect
|
|
|
|
move.w #$A8AD,D0 ; Unpatch _PtInRect
|
|
move.l $9CE+4,A0 ; We saved it in ToolScratch
|
|
dc.w $A047 ; _SetTrapAddress
|
|
|
|
movem.l (SP)+,A0/D0
|
|
|
|
unlk A6 ; See the saving code for details
|
|
move.b (SP)+,$BFF
|
|
move.l (SP)+,$120
|
|
move.l (SP)+,$A8C
|
|
move.l (SP)+,$2BA
|
|
move.l (SP)+,$9CE+4
|
|
move.l (SP)+,$9CE
|
|
move.l (SP)+,$3F8+4
|
|
move.l (SP)+,$3F8
|
|
move.l #-1,$14A
|
|
movem.l (SP)+,A1-A5/D1-D7
|
|
rts
|
|
|
|
|
|
.PushPaddedString ; trashes A1-A2,D0-D2, but must preserve A0
|
|
move.l (SP)+,A2
|
|
|
|
move.l A0,-(SP) ; backup
|
|
moveq.l #0,D0
|
|
clr.w -(SP)
|
|
move.l A0,-(SP)
|
|
dc.w $A88C ; _StringWidth
|
|
move.w D5,D0
|
|
sub.w (SP)+,D0
|
|
bgt.s .notzero
|
|
moveq.l #0,D0
|
|
.notzero
|
|
asr.w #3,D0 ; divide the leftover by twice a Chicago space
|
|
move.l (SP)+,A0 ; restore backup
|
|
|
|
clr.w D1
|
|
move.b D0,D1
|
|
add.b (A0),D1
|
|
addq.b #1,D1
|
|
bclr #0,D1 ; this is the spaced-out length in memory
|
|
|
|
clr.w D2
|
|
.spaceloop
|
|
cmp.w D2,D1
|
|
beq.s .spacedone
|
|
move.w #$2020,-(SP)
|
|
addq.w #2,D2
|
|
bra.s .spaceloop
|
|
.spacedone
|
|
move.w D1,-(SP)
|
|
|
|
|
|
lea 2(SP),A1 ; bm dest
|
|
add.w D0,A1
|
|
|
|
clr.l D0
|
|
move.b (A0),D0
|
|
move.l A0,-(SP)
|
|
addq.l #1,A0 ; bm src
|
|
dc.w $A22E ; _BlockMoveData
|
|
move.l (SP)+,A0
|
|
|
|
|
|
jmp (A2)
|
|
|
|
|
|
.MyPtInRect
|
|
move.l $9CE,D0
|
|
sub.w D0,10(SP)
|
|
swap D0
|
|
sub.w D0,8(SP)
|
|
|
|
move.l $9CE+4,A0
|
|
jmp (A0)
|
|
|
|
|
|
.GetA0
|
|
lea .TrailingList+4,A0
|
|
rts
|
|
|
|
|
|
.AdvanceA0
|
|
moveq.l #1,D0
|
|
add.b (A0),D0
|
|
add.l D0,A0
|
|
and.l #1,D0 ; align to 2-byte boundary
|
|
add.l D0,A0
|
|
lea 4(A0),A0 ; skip the 4-byte header
|
|
rts
|
|
|
|
|
|
.MyDSAlertTabStart
|
|
dc.w 1 ; NumEntries
|
|
|
|
; Our only alert definition
|
|
dc.w $2012 ; ID of this error
|
|
dc.w 10 ; length of remaining items
|
|
dc.w 0 ; primary text definition ID
|
|
dc.w 0 ; secondary text definition ID
|
|
dc.w 0 ; icon definition ID
|
|
dc.w 0 ; procedure definition ID
|
|
dc.w $1993 ; button definition ID
|
|
.MyDSAlertTabEnd
|
|
|
|
.TrailingList
|
|
_BoundaryLabelAtEndOfBootPicker_
|