;********************************************************************
;Program:       CopperMenu
;Contents:      Menu to easily select files by Mouse
;Version:       V2.0m
;Author:        Volker Oth [vo]
;Address:       Kopernikusstr.1, 6453 Seligenstadt
;Copyright:     None, let my name in - read MenuMaker.DOC
;Language:      Assembler
;Translator:    SEKA
;History:       V1.0  [vo] 18/10/1989 first Version written in
;                     Modula 2 - not released on PD
;               V2.0  [vo] 12/07/1990 very new Version with Colour-
;                     Scroll and Shadows - not released, either
;               V2.0c [vo] 06/10/1990 new kind of loading using
;                     ColdCapture - not released, again
;               V2.0m [vo] 28/10/1990 V2.0c translated to Assembler
;                     added switching Power-LED off/on
;*******************************************************************

Start:
;****************************** DEFINING OF CONSTANTS ***************
;****************************** System
ExecBase    =     $04         ; Absolute pointer at ExecBase
ColdCapture =     $2A         ; pointer at ColdCapture
Level3Int   =     $6C         ; contains Level 3 Interrupt
Mouse       = $BFE001         ; contains Left Button and Power-LED
CIAAICR     = $BFED01         ; CIA A Interrupt Control Register
DMABase     = $DFF000         ; Base Address of DMA
VPOSR       = $DFF004         ; Read Vertical raster Position
Joy0Dat     = $DFF00A         ; Mouse
Joy1Dat     = $DFF00C         ; Joystick
POTGOR      = $DFF016         ; Right Button
INTENA      = $DFF09A         ; Interrupt enable Mask (write)
INTENAR     = $DFF01C
COP1LCH     =   $0080         ; Pointer at 1st Copperlist (High Word)
COPJMP1     =   $0088         ; CopperList 1 Counter
DIWSTRT     =   $008E         ; offset to DMA : upper left corner
DIWSTOP     =   $0090         ; lower right corner
DDFSTRT     =   $0092         ; bitplane-data-start
DDFSTOP     =   $0094         ; bitplane-data-stop
DMACON      =   $0096         ; DMA-Control-Register
BPL1PTH     =   $00E0         ; Pointer at BitPlane 1 (High Word)
BPL1PTL     =   $00E2         ; (Low Word)
BPL2PTH     =   $00E4         ; Pointer at BitPlane 2 (High Word)
BPL2PTL     =   $00E6         ; (Low Word)
BPLCON0     =   $0100         ; Bitplane Control 1
BPLCON1     =   $0102         ; Bitplane Control 2
BPLCON2     =   $0104         ; BitPlane Control 3
BPL1MOD     =   $0108         ; Bytes to add to even bitplanes
BPL2MOD     =   $010A         ; same for odd bitplanes
C0          =   $0180         ; Colour 0 Register
C1          =   $0182         ; Colour 1
C2          =   $0184         ; Colour 2
StartList   =      38         ; Copper-Init-Address
Forbid      =    -132         ; Exec.Library-Subroutine-Offsets
Permit      =    -138
AllocMem    =    -198
FreeMem     =    -210
OpenLibrary =    -552
CloseLibrary=    -414
AddIntServer=    -168
RemIntServer=    -174
Move        =    -240         ; Graphics.Library-Subroutine-Offsets
Text        =    -060
SetAPen     =    -342
ClearScreen =    -048
InitBitMap  =    -390
InitRastPort=    -198
ScrollRaster=    -396
;****************************** Program
CopOffset   =      41
BeamOffset  =      -1
StartOffset =      -6
BeamHeight  =      11
Height      =      10
CHeight     =       8
Broad       =       8
ScreenX     =     320
ScreenY     =     256
RightScreen = 3 * Broad + ScreenX
CharX       = ScreenX + Broad
JoySensity  =       3
Terminator  =       0
StringLen   =      40
PlaneSize   = RightScreen*ScreenY/8 ; SIZE OF 1 BITPLANE
CopSize     =    1000
FrontPen    =       1
ShadowPen   =       2
time        =    6000

; ***************************** MAIN **************************
MAIN:
  MOVEM.L D0-D7/A0-A6,-(A7)
  MOVE.L ExecBase,A6
  JSR Forbid(A6)              ; Disable MultiTasking
  MOVE.L #PlaneSize * 2,D0
  MOVE.L #$10002,D1           ; ChipMem + free
  JSR AllocMem(A6)            ; Allocate 2 BitPlanes
  MOVE.L D0,PL1High           ; Enter Addresses in BitMap-Structure
  ADD.L #PlaneSize,D0
  MOVE.L D0,PL2High
  MOVE.L #CopSize,D0
  MOVE.L #$10002,D1
  JSR AllocMem(A6)            ; Allocate Copperlist
  MOVE.L D0,NewCopList
  MOVE.L #CopSize,D0
  MOVE.L #$10002,D1
  JSR AllocMem(A6)            ; Allocate Buffer for switching Coplist
  MOVE.L D0,CopBuffer
  LEA GfxName,A1
  CLR.L D0                    ; no special Version
  JSR OpenLibrary(A6)         ; Open Graphics.Library
  MOVE.L D0,GfxBase
;****************************** INIT VARIABLES
  JSR Count                   ; count titles,items; init number
  CLR.L D0
  MOVE.B number,D0
  MULU #Height,D0             ; D0 = UsedPixels (number*Height)
  MOVE.L #ScreenY,D1
  SUB.L D0,D1                 ; StartGfxPos[D1] =
  DIVU #02,D1                 ;   (ScreenY-UsedPixels)/2)
  AND.L #$0000FFFF,D1         ; kill upper bits
  ADD.L #StartOffSet,D1
  MOVE.B D1,StartGfxPos       ; save StartGfxPos
  ADD.B #CopOffSet,D1
  MOVE.B D1,StartCopPos       ; save StartCopPos
  JSR DefineScroller          ; ScrollCopPos,ScrollGfxPos,ScrollBottom
;****************************** Init all other
  CLR.L D0
  MOVE.W MaxCol,D0
  MULU #02,D0
  MOVE.B D0,ColMax            ; save ColMax = MaxCol * 2
  SUB.B #02,D0
  MOVE.B D0,offa              ; save Offset A for lower line
  CLR.L D0
  MOVE.B StartCopPos,D0
  SUB.L #Height,D0
  CMP.L #00,D0
  BGT GO_ON                   ; IF Up [D0] < 0 THEN
    MOVE.L #CopOffset,D0      ; Up [D0] = CopOffset
GO_ON:
  MOVE.B D0,Up                ; save Up  (StarCopPos-Height)
  CLR.L D0
  MOVE.B items,D0
  MULU #Height,D0             ; number*Height
  ADD.B ScrollCopPos,D0       ; ScrollGfxPos+CopOffset+items*Height
  ADD.B #CHeight*3,D0
  MOVE.B D0,Down              ; save Down
  MOVE.L NewCopList,coplist
  JSR Draw_Copper_List
;****************************** Init Planes and Rastport
  MOVE.L GfxBase,A6
  LEA BitMap,A0
  MOVE.L #02,D0               ; 2 BitPlanes
  MOVE.L #RightScreen,D1      ; Broad
  MOVE.L #ScreenY,D2          ; Height
  JSR InitBitMap(A6)
  LEA RastPort,A1
  JSR InitRastPort(A6)
  MOVE.L #BitMap,R_BitMap     ; enter bitmap-struct in rastport-struct
  MOVE.B #00,DrawMode         ; Set Mode
  JSR Show_All                ; Print text
; ***************************** Init Mousetest
  CLR.L D0
  MOVE.B StartCopPos,D0
  ADD.B #Height+BeamOffset,D0
  CLR.L D1
  MOVE.B titles,D1
  MULU #Height,D1
  ADD.B D1,D0                 ; clinestart= StartCopPos + BeamOffset
  MOVE.B D0,clinestart        ;           + Height + Titles * Height
  MOVE.W Joy0Dat,olddat
  CLR.L D1
  CLR.L D2
  MOVE.L #256,D0
  MOVE.B items,D2
  DIVU D2,D0
  AND.L #$0000FFFF,D0
  MULU #256,D0                ; Magic[D0] = (256 DIV items) *256
  MOVE.W D0,magic
;****************************** Init DMA
  MOVE.L #DMABase,A5
  BSR CHECKVHPOS
  MOVE.W #%0000000110100000,DMACon(A5) ; Stop copper,bitpl,sprites
  MOVE.W #$3081,DIWSTRT(A5)   ; Display Window Start
  MOVE.W #$29C1,DIWSTOP(A5)   ; Display Window Stop
  MOVE.W #$0038,DDFSTRT(A5)   ; Datafetch-Start
  MOVE.W #$00D0,DDFSTOP(A5)   ; Datafetch-Stop
  MOVE.W #%0010001000000000,BPLCON0(A5); two bitplanes,colour on
  CLR.W BPLCON1(A5)           ; no scrolling
  CLR.W BPLCON2(A5)           ; sprite priority equal
  MOVE.W #4,BPL1MOD(A5)       ; Add 4 Bytes after line (even)
  MOVE.W #4,BPL2MOD(A5)       ; same for odd bitmaps
  MOVE.L NewCopList,COP1LCH(A5) ; enter new copperlist
  CLR.W COPJMP1(A5)           ; reset copperlist-counter
  MOVE.W #%1000000110000000,DMACon(A5) ; Start Copper,Bitplane
;****************************** Init Interrupt
  MOVE.W INTENAR,oldintmask
  OR.W #%1100000000000000,oldintmask
  MOVE.W #%001111111111111,INTENA ; all interrupts off
  MOVE.L Level3Int,OldIrq     ; save former interrupt-vector
  MOVE.L #Scroll,Level3Int    ; enter new vector
  MOVE.W #%1000000000100000,INTENA ; all interrupts on
; ***************************** MAIN LOOP
MAIN_LOOP_START:
    BTST #6,Mouse
    BEQ MAIN_LOOP_END         ; left Button pressed ???
      BTST #10,POTGOR         ; right Button pressed ???
      BNE LED_END
        BCHG #1,Mouse         ; invert LED-Bit
LED_END:
      MOVE.L CopBuffer,coplist
      JSR Draw_Copper_List    ; Draw new copperlist in buffer
      MOVE.L NewCopList,MemPtr
      MOVE.L CopBuffer,NewCopList
      MOVE.L MemPtr,CopBuffer ; swap coplists
      MOVE.L #DMABase,A5
      MOVE.L NewCopList,COP1LCH(A5) ; start new list
      BSR Wait                ; Wait a little bit 
      BRA MAIN_LOOP_START
MAIN_LOOP_END:
;****************************** Kill Interrupt
  MOVE.W #%0000000000100000,INTENA
  MOVE.L Oldirq,Level3Int
  MOVE.W oldintmask,INTENA
;****************************** Set DMA back
  MOVE.L GfxBase,A6
  MOVE.L #DMABase,A5
  MOVE.W #%0000000110000000,DMACon(A5)
  MOVE.L StartList(A6),COP1LCH(A5)
  CLR.W COPJMP1(A5)
  MOVE.W #%1000000110100000,DMACon(A5)
;****************************** Close Libraries
  MOVE.L ExecBase,A6
  MOVE.L GfxBase,A1
  JSR CloseLibrary(A6)
;****************************** Set System back
  MOVE.L PL1High,A1
  MOVE.L #PlaneSize*2,D0
  JSR FreeMem(A6)             ; Free Bitplanes
  MOVE.L NewCopList,A1
  MOVE.L #Copsize,D0
  JSR FreeMem(A6)             ; Free Coplist
  MOVE.L CopBuffer,A1
  MOVE.L #CopSize,D0
  JSR FreeMem(A6)             ; Free CoplistBuffer for switching
;****************************** Is there a Loaddefinition ???
  LEA Load,A0                 ; to disable last part via
  CMP.B #00,(A0)              ;   MenuMaker
  BEQ END
;****************************** Alloc and put address in ColdCapture
  MOVE.L #44,D0               ; 44 Bytes
  MOVE.L #01,D1               ; Public
  JSR AllocMem(A6)
  MOVE.L D0,A0                ; Adr to A0
  MOVE.L D0,MemPtr            ; save D0
  LEA Load,A1                 ; A1 at Loaddefinitionbuffer
  MOVE.B chosen,D1
  MULU #40,D1
  SUB.L #40,D1                ; D1 = chosen*40 -40  (= Offset)
  ADD.L D1,A1
  CLR.L D0                    ; D0 = counter
COPYSTART:
    MOVE.B (A1)+,(A0)+        ; copy loaddef to buffer
    ADD.L #01,D0
    CMP.L #40,D0
    BNE COPYSTART
  MOVE.L ExecBase,A0
  MOVE.L ColdCapture(A0),A1   ; A1 at Ptr in ColdCapture
  LEA ColdCapture(A0),A2      ; A2 at ColdCapture
  MOVE.L MemPtr,A3            ; A3 at Allocated String
  MOVE.L A1,40(A3)            ; old ColdCapture to StringPos 40-44
  MOVE.L MemPtr,(A2)          ; Put Address in ColdCapture
END:
  MOVE.L ExecBase,A6
  JSR Permit(A6)              ; close friend of Kermit
  MOVEM.L (A7)+,D0-D7/A0-A6
  RTS

;****************************** Wait *****************************
Wait:
  MOVE.L #00,D0
Wait_Start:
    ADD.L #01,D0
    CMP.L #time,D0
    BLT Wait_Start
  RTS

;****************************** Check VHPOS **********************
CHECKVHPOS:                   ; This is the original VBeamPos
    MOVE.L VPOSR,D7           ; it doesn`t work if V0-V8 is
    ASR.L #8,D7               ; changed while reading
    AND.L #$01FF,D7           ; (but better than none)
    CMP.L #25,D7              ; it should avoid the vertical
  BGE CHECKVHPOS              ; "sprite-line"
  RTS

; **************************** StringLength **********************
StringLength:                ; (a0 at string, d0 gives back Length)
  CLR.L D1
  CLR.L D0
  String_Loop:
    MOVE.B (A0)+,D1
    CMP.B #Terminator,D1
    BEQ String_End
    ADD.L #01,D0
    CMP.L #StringLen,D0
    BNE String_Loop
String_End:
  RTS

; *************************** Test VertPos ***********************
Pal:                        ; to allow YPos bigger than 256
  AND.L #$000000FF,D1
  CMP.L #56,D1
  BGT Pal_End
    CMP.B #$FF,PalFlag
    BEQ Pal_End
      MOVE.L #$FFE1FFFE,(A0)+
      MOVE.B #$FF,PalFlag
Pal_End:
  RTS

; **************************** Draw Copperlist *******************
Draw_Copper_List:            ; line of chosen in cline
  MOVE.L GfxBase,A6
  MOVE.L CopList,A0          ; start of buffer for coplist
  MOVE.W #BPL1PTH,(A0)+
  MOVE.W PL1High,(A0)+
  MOVE.W #BPL1PTL,(A0)+
  MOVE.W PL1Low,(A0)+
  MOVE.W #BPL2PTH,(A0)+
  MOVE.W PL2High,(A0)+
  MOVE.W #BPL2PTL,(A0)+
  MOVE.W PL2Low,(A0)+
  MOVE.B #00,PalFlag
  MOVE.W #C0,(A0)+
  MOVE.W bocol,(A0)+         ; set C0 = BorderColour
;***************************** UPPER LINE
  CLR.L D1
  MOVE.B Up,D1               ; D1 = copline
  MOVE.B D1,(A0)+
  MOVE.B #01,(A0)+
  MOVE.W #$FFFE,(A0)+
  LEA CscrollP,A2            ; A2 = Cardptr
  MOVE.L #51,D2              ; D2 = I
  CLR.L D3
  MOVE.B offb,D3
C_Loop_1:
    MOVE.B D1,(A0)+          ; Wait till Y = copline
    MOVE.B D2,(A0)+          ; Wait till X = I
    MOVE.W #$FFFE,(A0)+
    MOVE.W #C0,(A0)+
    MOVE.W (A2,D3),(A0)+     ; MOVE ScrollColour in 0
    ADD.B #02,D2             ; INC VertPos
    ADD.B #02,D3             ; INC Offset
    CMP.B ColMax,D3
    BNE C_LOOP_1_IF
    CLR.L D3
C_LOOP_1_IF:
    CMP.B #81,D2
    BNE C_Loop_1
  ADD.B #02,offb
  CLR.L D0
  MOVE.B ColMax,D0
  CMP.B offb,D0
  BNE C_LOOP_1_END
  CLR.B offb
C_LOOP_1_END:
  MOVE.B D1,(A0)+
  MOVE.B #$E1,(A0)+
  MOVE.W #$FFFE,(A0)+        ; Wait till copline,1
  MOVE.W #C0,(A0)+
  MOVE.W bacol,(A0)+         ; col 0 = BackgroundCol
  MOVE.W #C2,(A0)+
  MOVE.W tscol,(A0)+         ; col 2 = TitleShadowCol
;***************************** TITLE
  MOVE.B StartCopPos,D1      ; copline = StartCopPos
  MOVE.L #00,D4              ; D4 = J
C_LOOP_2_OUT:
    MOVE.L #00,D2            ; D2 = I
    LEA CTitle,A2            ; A2 = CardPtr
  C_LOOP_2_IN:
    MOVE.B D1,(A0)+
    MOVE.B #01,(A0)+
    MOVE.W #$FFFE,(A0)+      ; Wait till copline,1
    MOVE.W #C1,(A0)+
    MOVE.W (A2)+,(A0)+       ; Move C1
    ADD.B #01,D1             ; INC copline
    ADD.B #01,D2             ; INC I
    CMP.B #CHeight,D2
    BNE C_LOOP_2_IN
  ADD.B #02,D1
  ADD.B #01,D4
  CMP.B titles,D4
  BNE C_LOOP_2_OUT
; **************************** SCROLLER
  MOVE.B ScrollCopPos,D1     ; copline = ScrollCopPos
  LEA CScrollP,A2            ; A2 = CardPtr
  MOVE.L #00,D2              ; D2 = I
  MOVE.B offc,D3
C_LOOP_3_START:
    MOVE.B D1,(A0)+
    MOVE.B #$01,(A0)+
    MOVE.W #$FFFE,(A0)+      ; WAIT till copline,1
    MOVE.W #C1,(A0)+
    MOVE.W (A2,D3),(A0)+     ; C1
    ADD.B #02,D3             ; INC Offset
    ADD.B #01,D2             ; INC I
    ADD.B #01,D1             ; INC copline
    CMP.B ColMax,D3
    BNE C_LOOP_3_IF
    CLR.L D3
C_LOOP_3_IF:
    CMP.B #CHeight,D2
    BNE C_LOOP_3_START
  ADD.B #02,offc
  MOVE.B ColMax,D0
  CMP.B offc,D0
  BNE C_LOOP_3_END
  CLR.B offc
C_LOOP_3_END:
;***************************** Items
  ADD.B #01,D1               ; INC copline
  MOVE.B D1,(A0)+
  MOVE.B #01,(A0)+
  MOVE.W #$FFFE,(A0)+        ; Wait till copline,1
  MOVE.W #C1,(A0)+
  MOVE.W icol,(A0)+          ; c1 = ItemCol
  MOVE.W #C2,(A0)+
  MOVE.W iscol,(A0)+         ; c2 = ItemShadowCol
;***************************** Beam
  MOVE.B cline,D1            ; copline[D1] = i[cline] (chosen item )
  BSR Pal
  MOVE.B D1,(A0)+
  MOVE.B #01,(A0)+
  MOVE.W #$FFFE,(A0)+        ; Wait till copline,1
  MOVE.W #C1,(A0)+
  MOVE.W ccol,(A0)+          ; c1 = ChosenCol
  MOVE.W #C2,(A0)+
  MOVE.W cscol,(A0)+         ; c2 = ChosenShadowCol
  LEA CBeam,A2               ; CardPtr = CBeam
  CLR.L D2                   ; i[D2] = 0
  MOVE.W #C0,(A0)+
  MOVE.W (A2)+,(A0)+         ; c0 = BeamColour[0]
  ADD.B #01,D1               ; INC copline
C_LOOP_4_START:
    BSR Pal
    MOVE.B D1,(A0)+
    MOVE.B #01,(A0)+
    MOVE.W #$FFFE,(A0)+      ; Wait till copline,1
    MOVE.W #C0,(A0)+
    MOVE.W (A2)+,(A0)+
    ADD.B #01,D1             ; INC copline
    ADD.B #01,D2
    CMP.B #BeamHeight-2,D2
    BLE C_LOOP_4_START
C_LOOP_4_END:
;***************************** ITEMS BACK
  BSR Pal
  MOVE.B D1,(A0)+
  MOVE.B #01,(A0)+
  MOVE.W #$FFFE,(A0)+        ; Wait till copline,1
  MOVE.W #C0,(A0)+
  MOVE.W bacol,(A0)+         ; c0 = BackgroundCol
  MOVE.W #C1,(A0)+
  MOVE.W icol,(A0)+          ; c1 = ItemCol
  MOVE.W #C2,(A0)+
  MOVE.W iscol,(A0)+         ; c2 = ItemShadowCol
;***************************** LOWER LINE
  MOVE.B down,D1             ; D1 = copline
  BSR Pal
  LEA CscrollP,A2            ; A2 = Cardptr
  MOVE.L #51,D2              ; D2 = I
  MOVE.B offa,D3
  MOVE.B D1,(A0)+
  MOVE.B #01,(A0)+
  MOVE.W #$FFFE,(A0)+
C_Loop_5:
    MOVE.B D1,(A0)+          ; Wait till Y = copline
    MOVE.B D2,(A0)+          ; Wait till X = I
    MOVE.W #$FFFE,(A0)+
    MOVE.W #C0,(A0)+
    MOVE.W (A2,D3),(A0)+     ; MOVE ScrollColour in 0
    ADD.B #02,D2             ; INC VertPos
    SUB.B #02,D3             ; INC Offset
    CMP.B #00,D3
    BGT C_LOOP_5_IF
      CLR.L D3
      MOVE.B ColMax,D3
      SUB.B #02,D3
C_LOOP_5_IF:
    CMP.B #81,D2
    BNE C_Loop_5
      ADD.B #02,offa
      MOVE.B ColMax,D0
      CMP.B offa,D0
      BNE C_LOOP_5_END
        CLR.B offa
C_LOOP_5_END:
  MOVE.B D1,(A0)+
  MOVE.B #$E1,(A0)+
  MOVE.W #$FFFE,(A0)+        ; Wait till copline,1
  MOVE.W #C0,(A0)+
  MOVE.W bocol,(A0)+         ; col 0 = BackgroundCol
  MOVE.B #$FF,(A0)+
  MOVE.B #$FF,(A0)+
  MOVE.W #$FFFE,(A0)+
COPEND:
  RTS

;***************************** CENTER STRING *****************
CenterString:                ; A0 at string, D1 at Y-Position
  MOVEM.L D0-D7/A0-A6,-(SP)
  MOVE.L A0,StringPtr
  MOVE.B D1,YPos
  JSR StringLength
  MOVE.B D0,Length
  MOVE.L GfxBase,A6
  MOVE.L #ShadowPen,D0       ; Colour 2
  LEA RastPort,A1
  JSR SetAPen(A6)            ; Change Colour
  CLR.L D0
  MOVE.B Length,D0
  MULU #Broad,D0             ; pixlen[D0] (length*broad)
  MOVE.L #ScreenX,D2
  SUB.L D0,D2                ; D2 = ScreenX - pixlen
  MOVE.L D2,D0               ; D0 = D2
  DIVU #02,D0                ; Xpos[D0] ((ScreenX - pixlen) / 2)
  AND.L #$0000FFFF,D0        ; clear upper Bytes
  MOVE.B D0,XPos             ; save Xpos
  ADD.B #01,D0               ; X+1
  CLR.L D1
  MOVE.B YPos,D1             ; D1 = Ypos (given)
  ADD.B #01,D1               ; Y+1
  LEA RastPort,A1
  JSR Move(A6)               ; SetCursor to D0,D1
  MOVE.L StringPtr,A0        ; str to A0
  CLR.L D0
  MOVE.B Length,D0
  JSR Text(A6)               ; Write Shadow
  MOVE.L #FrontPen,D0        ; Colour 1
  LEA RastPort,A1
  JSR SetAPen(A6)            ; Change Colour
  CLR.L D0
  MOVE.B XPos,D0
  CLR.L D1
  MOVE.B YPos,D1
  JSR Move(A6)
  MOVE.L StringPtr,A0
  MOVE.B Length,D0
  JSR Text(A6)               ; Write Text
  MOVEM.L (SP)+,D0-D7/A0-A6
  RTS
; **************************** COUNT ********************************
Count:
  CLR.B titles
  CLR.B items
  CLR.B number
  LEA Title,A2               ; Title[0]
SHOW_COUNT_1_START:
    MOVE.B (A2),D1           ; D1 = Title^[0]
    CMP.B #Terminator,D1
    BEQ SHOW_COUNT_1_END
    ADD.L #40,A2
    ADD.B #01,titles
    ADD.B #01,number
    CMP.B #03,titles         ; Already 3 titles ?
    BNE SHOW_COUNT_1_START
SHOW_COUNT_1_END:
  LEA Show,A2                ; Show[0]
SHOW_COUNT_2_START:
    MOVE.B (A2),D1           ; D1 = Show^[0]
    CMP.B #Terminator,D1
    BEQ SHOW_COUNT_2_END
    ADD.L #40,A2
    ADD.B #01,items
    ADD.B #01,number
    CMP.B #20,items          ; Already 20 items ?
    BNE SHOW_COUNT_2_START
SHOW_COUNT_2_END:
  RTS

; **************************** Show All ***************************
Show_All:
  CLR.L D1
  MOVE.B StartGfxPos,D1      ; D1 = CurrentY
  CLR.L D2                   ; I
  LEA Title,A2               ; TitleStart
SHOW_LOOP_1_START:
    MOVE.L A2,A0             ; StringPtr
    JSR CenterString
    ADD.B #01,D2             ; INC I
    ADD.L #40,A2             ; INC StringPtr
    ADD.B #Height,D1         ; INC CurrentY
    CMP.B titles,D2          ; Already all titles ?
    BNE SHOW_LOOP_1_START
SHOW_LOOP_1_END:
  MOVE.L #00,D2              ; I
  ADD.B #Height*2,D1         ;
  LEA Show,A2                ; ShowStart
SHOW_LOOP_2_START:
    MOVE.L A2,A0             ; StringPtr
    JSR CenterString
    ADD.B #01,D2             ; INC I
    ADD.L #40,A2             ; INC StringPtr
    ADD.B #Height,D1         ; INC CurrentY
    CMP.B items,D2           ; Already all items ?
    BNE SHOW_LOOP_2_START
SHOW_LOOP_2_END:
  RTS

; **************************** Define Scroller ***********************
DefineScroller:
  CLR.L D1
  CLR.L D2
  MOVE.B StartGfxPos,D1
  MOVE.B titles,D2
  MULU #Height,D2            ; D2 = titles*Height
  ADD.L D2,D1
  ADD.L #Height/2,D1         ; D1 = StartGfxPos+titles*Height+Height/2
  MOVE.L D1,ScrollBottom     ; save ScrollBottom
  ADD.B #CopOffset,D1
  MOVE.B D1,ScrollCopPos     ; save ScrollcopperPosition
  MOVE.L ScrollBottom,D1
  SUB.B #Height,D1
  MOVE.L D1,ScrollGfxPos     ; save ScrollGfxPos
  ADD.L #CHeight+1,D1        ; +1 for inaccurate programming
  MOVE.L D1,CharY
  MOVE.B #JoySensity,ScrollStep
  MOVE.B #01,ScrollOffset    ; init Scrolloffset
  MOVE.L #ScrollDat,CharPtr  ; set CharPtr at ScrollText-Buffer
  RTS

; **************************** IRQ Routine ***************************
Scroll:
  MOVEM.L D0-D7/A0-A6,-(SP)
  MOVE SR,-(SP)
  MOVE.L GfxBase,A6
  LEA RastPort,A1
  CLR.L D1                   ; no pixel in Y
  CLR.L D0
  MOVE.B scrolloffset,D0     ; scrolloffset in X
  ADD.B D0,scrollpix
  CLR.L D2
  MOVE.L ScrollGfxPos,D3     ; upper left corner : 0,ScrollGfxPos
  MOVE.L #RightScreen,D4
  MOVE.L ScrollBottom,D5     ; lower right : LeftScreen,ScrollBottom
  JSR ScrollRaster(A6)
  CMP.B #Broad,scrollpix
  BLT Joy_Test               ; IF scrollpix <= SmallBroad
PrintChar:
    LEA RastPort,A1
    MOVE.L #CharX,D0         ; CX
    SUB.B #Broad,scrollpix   ; ScrollOffset
    SUB.B scrollpix,D0       ; CX - ScrollOffset
    MOVE.L CharY,D1          ; CY
    JSR Move(A6)             ; A6 and A1 should be unchanged
    LEA RastPort,A1
    MOVE.L CharPtr,A0        ; CharPointer
    MOVE.L #01,D0
    JSR Text(A6)             ; Print new Char
    ADD.L #01,CharPtr        ; INC Charpointer
    MOVE.L CharPtr,A0
    CMP.B #Terminator,(A0)   ; END OF Scroller ?
    BNE Print_End
      MOVE.L #ScrollDat,CharPtr
Print_End:
    BRA IRQ_END
; **************************** JoyTest
Joy_Test:
  MOVE.W Joy1Dat,D0
  BTST #1,D0
  BEQ JOY_1_END
    CMP.B #00,ScrollStep
    BLE JOY_1_END            ; ScrollStep <= 0
      SUB.B #01,ScrollStep   ; ELSE
  JOY_1_END:
  BTST #9,D0
  BEQ JOY_2_END
    CMP.B #JoySensity*Broad-1,ScrollStep
    BGE JOY_2_END            ; ScrollStep >= JoySensity*Broad
      ADD.B #01,ScrollStep   ; ELSE
  JOY_2_END:
  CLR.L D0
  MOVE.B ScrollStep,D0
  DIVU #JoySensity,D0        ; MOVE (ScrollStep DIV JoySensity to Left)
  AND.L #$0000FFFF,D0
  MOVE.B D0,scrolloffset     ; INC(scrollpix,Scrollstep div Joysensity)
;***************************** MouseTest
MouseTest:
  CLR.L D0
  MOVE.W Joy0Dat,D0
  CMP.W olddat,D0
  BEQ Mouse_DRAW
    MOVE.L D0,D1             ; save D0 in D1
    DIVU magic,D0
    AND.L #$0000FFFF,D0      ; cut off upper bits
    ADD.B #01,D0
    MOVE.B D0,chosen
    CMP.B items,D0
    BLE Mouse_IF
      MOVE.B #01,chosen
      BRA Mouse_DRAW
Mouse_IF:
    MOVE.W D1,olddat
Mouse_DRAW:
  MOVE.B clinestart,cline
  CLR.L D0
  MOVE.B chosen,D0
  MULU #Height,D0
  ADD.B D0,cline             ; cline = clinestart + chosen * Height
IRQ_END:
  MOVE (SP)+,SR
  MOVEM.L (SP)+,D0-D7/A0-A6
  DC.W $4EF9                 ; END Irq
OLDIRQ:
  BLK.L 1,0                  ; by jumping to old irq-address

;***************************** VARIABLES *****************************
offa:         BLK.B  1,0     ; offset for lower line col-scroll
offb:         BLK.B  1,0     ; offset for upper line col-scroll
offc:         BLK.B  1,0     ; offset for scoller`s colour-scroll
Down:         BLK.B  1,0     ; Y-Pos of lower line
Up:           BLK.B  1,0     ; Y-Pos of upper line
scrollpix:    BLK.B  1,0     ; pixels already scrolled
ScrollStep:   BLK.B  1,0     ; counter for Joystick-speed-control
scrolloffset: BLK.B  1,1     ; pixels to scroll
clinestart:   BLK.B  1,0     ; Copper-position of 1st item
cline:        BLK.B  1,0     ; Copper-position of actual item
StartGfxPos:  BLK.B  1,0     ; Y-Pos of 1st Title
StartCopPos:  BLK.B  1,0     ; Copper-Pos of 1st Title
ScrollCopPos: BLK.B  1,0     ; Copper-Pos of Scroll
PalFlag:      BLK.B  1,0     ; line 256 already passed ?
EVEN
olddat:       BLK.W  1,0     ; was the mouse moved ?
magic:        BLK.W  1,0     ; to define mouse-sensity
ScrollGfxPos: BLK.L  1,0     ; upper line of scroll
ScrollBottom: BLK.L  1,0     ; lower line of scroll
CharY:        BLK.L  1,0     ; Y-Pos of Char
titles:       BLK.B  1,0     ; how many titles (0-3)
items:        BLK.B  1,0     ; how many items (2-20)
number:       BLK.B  1,0     ; items + titles
chosen:       BLK.B  1,1     ; No. of chosen item
YPos:         BLK.B  1,0     ; saves X-Pos
XPos:         BLK.B  1,0     ; saves Y-Pos
Length:       BLK.B  1,0     ; saves Length
ColMax:       BLK.B  1,0     ; MaxCol*2

;***************************** Buffers,Fields,Structures ************
EVEN
MemPtr:       BLK.L  1,0     ; Pointer for some addresses
StringPtr:    BLK.L  1,0     ; pointer for string-addresses
CharPtr:      BLK.L  1,0     ; pointer at scroll`s current character
GfxBase:      BLK.L  1,0     ; saves Graphics-Base
BitMap:       BLK.W  4,0     ; Bitmap-Structure
 PL1High:       BLK.W  1,0
 PL1Low:        BLK.W  1,0
 PL2High:       BLK.W  1,0
 PL2Low:        BLK.W  1,0
 Planes:        BLK.L  8,0
RastPort:     BLK.L  1,0     ; RastPort-Structure
 R_BitMap:      BLK.L  6,0
 DrawMode:      BLK.L 20,0
NewCopList:   BLK.L  1,0     ; Pointer at new copperlist
CopBuffer:    BLK.L  1,0     ; Pointer at Buffer for switching
CopList:      BLK.L  1,0     ; Current Pointer (one of both)
oldintmask:   BLK.W  1,0
GfxName:      DC.B  "graphics.library",0

;***************************** DATA *********************************
; The following data can be changed using Menu Maker
EVEN
DC.B "!COOP!I",01            ; Colours ( 7 Words )
bocol:        DC.W $0000     ; Colour of Border
bacol:        DC.W $0000     ; Colour of Background
icol:         DC.W $0FFF     ; Colour of items
iscol:        DC.W $0777     ; Colours of items`s shadows
ccol:         DC.W $0FCC     ; Colour of chosen item
cscol:        DC.W $0D77     ; Colour of chosen item`s shadow
tscol:        DC.W $0007     ; Colour of title`s shadow

EVEN
DC.B "!COOP!I",02            ; Colours for ColourScroll (64 Words)
MaxCol:       DC.W $2E
CScrollP:
   DC.W $0CE3,$0AE3,$08E3,$07E3,$05E3,$04E3,$03E4,$03E5,$03E7,$03E8
   DC.W $03EA,$03EB,$03EC,$03EE,$03DE,$03CE,$03AE,$039E,$037E,$034E
   DC.W $033E,$043E,$063E,$073E,$083E,$0A3E,$0B3E,$0C3E,$0E3E,$0E3D
   DC.W $0E3B,$0E3A,$0E39,$0E37,$0E36,$0E34,$0E33,$0E53,$0E63,$0E83
   DC.W $0E93,$0EA3,$0EB3,$0EC3,$0EE3,$0DE3,$0000,$0000,$0000,$0000
   DC.W $0000,$0000,$0000,$0000,$0000,$0000,$0000,$0000,$0000,$0000
   DC.W $0000,$0000,$0000,$0000

EVEN
DC.B "!COOP!I",03             ; Title`s Colours ( 8 Words)
CTitle:       DC.W $011F,$033F,$044F,$055F,$066F,$055F,$044F,$033F

EVEN
DC.B "!COOP!I",04             ; Beam`s Colours  ( 11 Words)
CBeam:        DC.W $0500,$0700,$0900,$0B00,$0E00,$0F00,$0E00,$0B00
              DC.W $0900,$0700,$0500

EVEN
DC.B "!COOP!I",05             ; Title ( 3 * 40 Bytes )
Title:        DC.B "TITLE ONE"
              BLK.B 31,0            ; 40 - 9
              DC.B "TITLE TWO"
              BLK.B 31,0            ; 40 - 9
              DC.B "TITLE THREE"
              BLK.B 29,0            ; 40 - 11

EVEN
DC.B "!COOP!I",06             ; Items ( 20 * 40 Bytes )
Show:         DC.B "ITEM ONE"
              BLK.B 32,0
              DC.B "2nd ITEM"
              BLK.B 32,0
              DC.B "No THREE"
              BLK.B 32,0
              BLK.B 680,0           ; 17 * 40

EVEN
DC.B "!COOP!I",07             ; Loaddefinitions ( 20 * 40 Bytes )
Load:         BLK.B 800,0           ; 20 * 40

EVEN
DC.B "!COOP!I",08             ; Scrolltext ( 1000 Bytes )
ScrollDat:    DC.B "      Scroller" ; 14 Characters
              BLK.B 986,0           ; 1000 - 14
