   OPT c+,l-,o+

*****************************************************************************
*                                                                           *
*  Programma ............ BootPAL 1.0                                       *
*                                                                           *
*  Autore ............... Nico Francois                                     *
*                                                                           *
*  Sistema .............. Hisoft Devpac V2.14, Kickbench V1.2/1.3           *
*                                                                           *
*****************************************************************************

	incdir "dh1:IncludeDevpac/"  ; Modificare in base al proprio

	include "exec/types.i"
	include "exec/execbase.i"
	include "exec/memory.i"
	include "exec/resident.i"
	include "exec/exec_lib.i"
	include "graphics/gfxbase.i"
	include "graphics/graphics_lib.i"
	include "libraries/dos_lib.i"

NULL     equ   0

	movem.l d0/a0,-(a7)
	move.l ($4).w,a6
	lea DosName(PC),a1
	jsr _LVOOldOpenLibrary(a6)          ; Apre DOS
	lea DOSBase(PC),a1
	move.l d0,(a1)
	move.l d0,a6
	jsr _LVOOutput(a6)                  ; Legge stdout
	lea stdout(PC),a1
	move.l d0,(a1)
	lea header.txt(PC),a0               ; Stampa header su consolle
	move.l #header.len,d3
	bsr puts

	move.w $DFF004,d0                   ; Verifica nuovo Fat Agnus
	and.w #$2000,d0
	bne.s ok1MbAgnus
	addq.w #8,a7
	lea oldagnus.txt(PC),a0             ; Stampa mess. non disponibile
	move.l #oldagnus.len,d3
	move.l ($4).w,a6
	bra putsandexit
ok1MbAgnus:
	movem.l (a7)+,d0/a0                 ; Ricupera linea comando

	move.l ($4).w,a6
	move.b #0,0(a0,d0.w)                ; Terminato con NULL
cmdloop:
	move.b (a0)+,d0                     ; Ricerca 'I' o 'R'
	beq.s template
	cmp.b #'i',d0
	beq.s install
	cmp.b #'I',d0
	beq.s install
	cmp.b #'r',d0
	beq quit
	cmp.b #'R',d0
	beq quit
	bra.s cmdloop

template:                              ; Stampa linea uso
	lea usage.txt(PC),a0
	move.l #usage.len,d3
	bra putsandexit

install:
	move.l ($4).w,a6
	lea PortName(PC),a1
	jsr _LVOFindPort(a6)                ; Cerca nostra porta
	tst.l d0
	beq.s allocit
	lea already.txt(PC),a0              ; Trovata: gia' installati!
	move.l #already.len,d3
	bra putsandexit

allocit:
	move.l #BlockLen,d0
	move.l #MEMF_CHIP,d1                ; Alloca memoria per codice reset
	jsr _LVOAllocMem(a6)                ; Dev'essere in CHIP RAM
	tst.l d0
	bne.s memok
	lea nomem.txt(PC),a0                ; Terminata memoria ????
	move.l #nomem.len,d3
	bra putsandexit

memok:
	move.l d0,a5                        ; A5 = indirizzo della copia
	lea StartBlock(PC),a0
	move.l d0,a1
	move.l #BlockLen,d0
	jsr _LVOCopyMem(a6)                 ; Copia blocco in memoria allocata
	move.w #$4000,$DFF09A               ; DISABLE
	addq.b #1,IDNestCnt(a6)
	lea RomTagPtrs-StartBlock(a5),a0
	move.l KickTagPtr(a6),4(a0)         ; Vecchio romtag pointer in array
	beq.s yestag
	bset #7,4(a0)                       ; Setta bit se ve ne sono altri

yestag:
	move.l a0,KickTagPtr(a6)            ; Puntatore al nostro array
	lea RomTag-StartBlock(a5),a1
	move.l a1,(a0)                      ; Riempie nostro romtag pointer

	lea myMemList-StartBlock(a5),a1     ; Inizial. memlist e pone lista
	move.l a5,ML_SIZE+ME_ADDR(a1)       ; KickMemPtr per proteggere nostra
	move.l KickMemPtr(a6),d0            ; memoria
	move.l d0,LN_SUCC(a1)
	move.l a1,KickMemPtr(a6)
inittag:
	lea RomTag-StartBlock(a5),a1        ; Inizializza Romtag
	move.l a1,RT_MATCHTAG(a1)
	lea RT_SIZE(a1),a2
	move.l a2,RT_ENDSKIP(a1)
	lea TagName-StartBlock(a5),a2
	move.l a2,RT_NAME(a1)
	move.l a5,RT_INIT(a1)
	jsr _LVOSumKickData(a6)             ; Calcola checksum
	move.l d0,KickCheckSum(a6)
	lea Port-StartBlock(a5),a1          ; Inizializza ed aggiunge porta
	moveq #0,d0
	move.l d0,(a1)
	move.l d0,LN_PRED(a1)
	lea PortName-StartBlock(a5),a0
	move.l a0,LN_NAME(a1)
	jsr _LVOAddPort(a6)
	subq.b #1,IDNestCnt(a6)             ; ENABLE
	bge.s noenable
	move.w #$C000,$DFF09A
noenable:
	lea installed.txt(PC),a0            ; Informa utente dell'installazione
	move.l #installed.len,d3
	bra.s putsandexit

quit:
	lea PortName(PC),a1                 ; Siamo gia' installati
	jsr _LVOFindPort(a6)
	tst.l d0
	bne.s portfound
	lea nohandler.txt(PC),a0            ; Non, non posso terminarlo
	move.l #nohandler.len,d3
	bra.s putsandexit

portfound:
	move.l d0,a4                        ; Troviamo nostra porta, rimuoviamo
	move.l a4,a1
	jsr _LVORemPort(a6)

	move.w #$4000,$DFF09A               ; DISABLE
	addq.b #1,IDNestCnt(a6)

	lea myMemList-Port(a4),a1           ; Rimuove nostra lista dalla lista
	lea KickMemPtr(a6),a0               ; KickMemPtr
nextnode:
	move.l LN_SUCC(a0),d0
	cmp.l d0,a1
	beq.s foundmylist
	move.l d0,a0
	bra.s nextnode
foundmylist:
	move.l LN_SUCC(a1),d0
	move.l d0,LN_SUCC(a0)      ; LN_SUCC = 0,cosi' funziona anche per KickMem

	move.l RomTagPtrs-Port+4(a4),KickTagPtr(a6)  ; Recupera RomTag vecchio
	beq.s noclr2
	bclr #7,KickCheckSum(a6)
noclr2:
	jsr _LVOSumKickData(a6)             ; Calcola checksum
	move.l d0,KickCheckSum(a6)
	subq.b #1,IDNestCnt(a6)             ; ENABLE
	bge.s noenable2
	move.w #$C000,$DFF09A
noenable2:
	lea StartBlock-Port(a4),a1          ; Libera nostra copia
	move.l #BlockLen,d0
	jsr _LVOFreeMem(a6)
	lea removed.txt(PC),a0              ; Ed informa l'utente
	move.l #removed.len,d3

putsandexit:
	bsr.s puts                    ; Stampa stringa in A0 con lunghezza in D3
	move.l DOSBase(PC),a1
	jsr _LVOCloseLibrary(a6)      ; Chiude DOS ed esce
	moveq #0,d0
	rts

* Puntatore testo in A0, lunghezza in D3
puts:
	move.l a6,-(a7)
	move.l a0,d2
	move.l stdout(PC),d1
	move.l DOSBase(PC),a6
	jsr _LVOWrite(a6)
	move.l (a7)+,a6
	rts

header.txt:
	dc.b $9b,'1mBootPAL 1.0 ',$9b,'0m',$9b,'33mby Nico François',$9b,'0m',10
header.len equ *-header.txt
oldagnus.txt:
	dc.b 'You haven''t got the ECS 1Mb Agnus, so run out and buy one !',10,0
oldagnus.len equ *-oldagnus.txt
already.txt:
	dc.b 'PAL RomTag already installed !',10,0
already.len equ *-already.txt
usage.txt:
	dc.b 'Usage: BootPAL [I=INSTALL|R=REMOVE]',10,0
usage.len equ *-usage.txt
installed.txt:
	dc.b 'PAL RomTag installed, reset to activate !',10,0
installed.len equ *-installed.txt
nomem.txt:
	dc.b 'No memory for RomTag (I only need about 250 bytes) !?!',10,0
nomem.len equ *-nomem.txt
nohandler.txt:
	dc.b 'PAL RomTag not installed !',10,0
nohandler.len equ *-nohandler.txt
removed.txt:
	dc.b 'PAL RomTag removed !',10,0
removed.len equ *-removed.txt
DosName:
	dc.b 'dos.library',0
	EVEN
DOSBase:
	dc.l 0
stdout:
	dc.l 0

*****************************************************************************
* Questa e' la routine eseguita al reset

StartBlock:
	movem.l d0-d7/a0-a6,-(a7)
	move.l ($4).w,a6

	lea Port(PC),a1                     ; Aggiunge la nostra porta alla lista
	moveq #0,d0
	move.l d0,(a1)
	move.l d0,LN_PRED(a1)
	lea PortName(PC),a0
	move.l a0,LN_NAME(a1)
	jsr _LVOAddPort(a6)

* Ora mettiamo Amiga in modo PAL

	lea GfxName(PC),a1
	jsr _LVOOldOpenLibrary(a6)          ; Apre graphics.library
	move.l d0,a1
	move.w gb_DisplayFlags(a1),d0
	and.b #%11111110,d0                 ; Azzera flag NTSC
	or.b  #%00000100,d0                 ; Attiva flag PAL
	move.w d0,gb_DisplayFlags(a1)
	move.w #256,gb_NormalDisplayRows(a1); WorkBench alto 256 pixel
	or.b #LIBF_CHANGED,LIB_FLAGS(a1)
	move.l a1,a2
	jsr _LVOSumLibrary(a6)              ; Ricalcola checksum
	move.l a2,a1
	jsr _LVOCloseLibrary(a6)
	move.b #50,VBlankFrequency(a6)      ; Cambia VBLANK
	or.b #LIBF_CHANGED,LIB_FLAGS(a6)
	jsr _LVOSumLibrary(a6)              ; Ricalcola checksum

************************
	move.w #32,$dff1dc                  ; Questo svolge tutta la magia
************************

endtag:
	movem.l (sp)+,d0-d7/a0-a6           ; Nel kickstart
	rts

RomTagPtrs:
	dc.l 0,0                            ; Array di puntatori ROMTag
GfxName:
	dc.b 'graphics.library',0
PortName:
	dc.b 'BootPAL.port',0               ; Nome della porta
TagName:
	dc.b 'PAL-boot',0                   ; Nome del tag
	EVEN

myMemList:                             ; Lista memoria resetproof
	ds.b LN_SIZE
	dc.w 1
	dc.l NULL
	dc.l BlockLen

Port:                                  ; Struttura nostra porta
	dc.l NULL
	dc.l NULL
	dc.b NT_MSGPORT
	dc.b 0
	dc.l NULL
	dc.b 0
	dc.b 0
	dc.l NULL
	ds.b 14

RomTag:              ; ROMTag per informare kickstart di cio' che vogliamo
	dc.w RTC_MATCHWORD
	dc.l NULL
	dc.l NULL
	dc.b RTF_COLDSTART
	dc.b 1
	dc.b 0
	dc.b -10
	dc.l NULL
	dc.l NULL
	dc.l 0

BlockLen equ *-StartBlock					; Lunghezza del blocco da copiare

*****************************************************************************

   END
