; ****************************
; ***     Custom-Chip      ***
; ***         Demo         ***
; ***     -----------      ***
; *** Amiga-Red/pa         ***
; ***   Januar 88          *** 
; ****************************
;
jmp Main
;
; *** Library Offsets (Exec)
Forbid = -30-102
Permit = -30-108
AllocMem = -30-168
FreeMem = -30-180
OpenLibrary = -30-522
CloseLibrary = -30-384
;
; *** Register I/O u. Custom-Chip
CC = $dff000  ; Basisadresse
VPOSR = 4 
JOY1DAT = $c
JOY0DAT = $a
BLTCON0 = $40
BLTCON1 = $42
BLTAPTH = $50
BLTAPTL = $52
BLTDPTH = $54
BLTDPTL = $56
BLTSIZE = $58
BLTAMOD = $64
BLTDMOD = $66
COP1LC = $80
COPJMP1 = $88
DIWSTART = $8e
DIWSTOP = $90
DDFSTRT = $92
DDFSTOP = $94
DMACON = $96
BPL1PTL = $e2
BPL1PTH =$e0
BPLCON0 = $100
BPLCON1 = $102
BPLCON2 = $104
BPL1MOD = $108
BPL2MOD = $10A
COLOR0 = $180
;
PRA = $bfe000+1
;
; *** sonstige Labels
ExecBase = 4
ChipRam = 2
Clear = ChipRam+$10000
;
XMax = 1024   ; gr”áte X- und
YMax = 1024   ;  Y-Koordinate
PlaneSize = YMax*XMax/8  ; in Byte
Mod = [XMax-320]/8       ; Modulo
;
CLStart = 38  ; Startup-CopperList
schwarz = 0   ; Bildschirmfarben
rot = $0f00   
gold = $0fb0
lamiga = $33  ; Tastaturcodes
ramiga = $31
ctrl = $39
;
; *** Datenbereich
Sprite0: dc.w $2b3c,$3600
dc.w $01c0,$01c0
dc.w $01c0,$01c0
dc.w $01c0,$01c0
dc.w $01c0,$01c0
dc.w $fe3f,$fe3f
dc.w $fe3f,$fe3f
dc.w $fe3f,$fe3f
dc.w $01c0,$01c0
dc.w $01c0,$01c0
dc.w $01c0,$01c0
dc.w $01c0,$01c0
dc.w 0,0
dc.w 0,0,0,0
SpriteSize = *-Sprite0
;
CopperList:
dc.w BPL1PTH,0  ; Copperliste ohne
dc.w BPL1PTL,0  ;  Adressen
dc.w $120,0,$122,0,$124,0,$126,0
dc.w $128,0,$12a,0,$12c,0,$12e,0
dc.w $130,0,$132,0,$134,0,$136,0
dc.w $138,0,$13a,0,$13c,0,$13e,0
dc.w $ffff,$fffe ; Ende CopperList
CLSize = *-CopperList
                 ; Zeiger auf
gfxbase: dc.l 0  ; graphics.lib
SpritePtr: dc.l 0  ; Spritedaten
UCopList: dc.l 0  ; CopperList
PlanePtr: dc.l 0  ; Bitplane
;
lSpalte: dc.l 0 ; Zeilen- und 
lZeile: dc.l 0  ; Spaltenposition
lPPtr: dc.l 0   ; linke obere
rSpalte: dc.l 0 ; und rechte
rZeile: dc.l 0  ; untere Ecke des 
rPPtr: dc.l 0   ; Blitter-fensters
;
Spalte: dc.l 0   ; Cursor-Spalte
Zeile: dc.l 0    ; Cursor-Zeile
VScrCount: dc.l 0  ; Scrollz„hler 
HScrCount: dc.l 0  ; vert./horiz.
MvCnt: dc.l 0    ; letzte Mauspos.
MhCnt: dc.l 0   ; horiz. und vert.
Delay: dc.w $00ff ; Delay Bitplane
Maske: dc.w $4000 ; Punktmaske
;
GLName: dc.b "graphics.library",0
even
;
Main:                ; Zeiger
  move.l ExecBase,a6 ; auf ExecLib
  move.l #GLName,a1 ; graphics.lib
  move.l #0,d0      ; ”ffnen
  jsr OpenLibrary(a6)
  move.l d0,gfxbase; Zeiger merken
  beq.l Ende
  ;
  move.l #PlaneSize,d0 ; Platz fr 
  move.l #Clear,d1    ; Bitplane 
  jsr AllocMem(a6)   ; holen
  move.l d0,PlanePtr  ; Zeiger 
  beq.l Ende         ; merken und 
  move.w d0,CopperList+6 ; in die 
  move.w PlanePtr,d0  ; CopperList
  move.w d0,CopperList+2; kopieren
  ;
  move.l #SpriteSize,d0 ; Speicher 
  move.l #ChipRam,d1  ; fr Sprite 
  jsr AllocMem(a6)  ; holen
  move.l d0,SpritePtr  ; merken
  beq FreePlane
  move.l #CopperList+10,a0; und in 
  move.l #8,d2        ; CopperList
  move.w SpritePtr,d1 ; kopieren
MLoop0:
  move.w d1,(a0)      ; Hi-Byte
  move.w d0,4(a0)     ; Lo-Byte
  move.l SpritePtr,d0 ; nach Kopie
  add.l #SpriteSize-8,d0 ; des
  move.l d0,d1    ; Zeigers von 
  lsr.l #8,d1     ; Sprite 0 die 
  lsr.l #8,d1    ; Adresse fr 
  addq.l #8,a0   ; die restlichen 
  subq.l #1,d2   ; Sprites auf 
  bne MLoop0     ; Dummy-Sprite 
  move.l SpritePtr,a0 ; „ndern
  move.l #Sprite0,a1 ; Spritedaten 
  move.l #SpriteSize,d0 ; in Chip-
MLoop1:             ; RAM kopieren
  move.l (a1)+,(a0)+
  subq.l #4,d0
  bpl Mloop1
  ;
  move.l #CLSize,d0 ; Speicher fr 
  move.l #ChipRam,d1 ; Copperliste
  jsr AllocMem(a6)   ; holen
  move.l d0,UCopList ; Zeiger fr
  move.l d0,a0       ; Kopie der
  move.l #CopperList,a1 ; Copper-
  move.l #CLSize,d0  ; liste ins 
Mloop2:           ; Chip-RAM 
  move.l (a1)+,(a0)+ ; kopieren
  subq.l #4,d0
  bpl Mloop2
  jsr forbid(a6) ; Taskswitch aus
  move.w #$03e0,CC+DMACON; DMA aus 
  move.l UCopList,CC+COP1LC
  move.w #0,CC+COPJMP1
  move.w #$3081,CC+DIWSTART
  move.w #$30c1,CC+DIWSTOP
  move.w #$0030,CC+DDFSTRT
  move.w #$00d0,CC+DDFSTOP
  move.w #Mod-2,CC+BPL1MOD
  move.w #Mod-2,CC+BPL2MOD
  move.w #0,CC+BPLCON2
  move.w Delay,CC+BPLCON1
  move.w #$1200,CC+BPLCON0
  move.w #$83e0,CC+DMACON
  move.b CC+JOY0DAT+1,d0; Mausz„h.
  move.b d0,MhCnt ; initialisieren
  move.b CC+JOY0DAT,d0
  move.b d0,MvCnt
  jsr Paint     ; Malunterprogramm
  move.l gfxbase,a4 ; Startupliste
  move.l CLStart(a4),CC+COP1LC 
  move.w #0,CC+COPJMP1 ; Start
  jsr permit(a6)  ; Taskswitch ein
FreeList:        ; Speicher wieder
  move.l UCopList,a1  ; freigeben
  move.l #CLSize,d0
  jsr FreeMem(a6)
FreeSprite:
  move.l SpritePtr,a1
  move.l #SpriteSize,d0
  jsr FreeMem(a6)
FreePlane:
  move.l PlanePtr,a1
  move.l #PlaneSize,d0
  jsr FreeMem(a6)
Ende:
  move.l gfxbase,a1 ; graphics.lib
  jsr CloseLibrary(a6) ; schlieáen
  clr.l d0
  rts             ; fertig!!
Paint:
  move.w #schwarz,CC+COLOR0
  move.l PlanePtr,a4  ; Bitplane-
PLoop:                  ; zeiger 
  move.b CC+JOY0DAT+1,d4
  move.b MhCnt,d5     ; Mauspos.
  move.b d4,MhCnt     ; horizontal
  sub.b d5,d4         ; lesen
  beq pl2         ; keine Bewegung
  blt pl1         ; nach links
  bsr right       ; nach rechts
  bra pl2
PL1:bsr left
PL2: move.b CC+JOY0DAT,d4
  move.b MvCnt,d5     ; Mauspos.
  move.b d4,MvCnt     ; vertikal
  sub.b d5,d4         ; lesen
  beq pl4         ; keine Bewegung
  blt pl3         ; nach oben
  bsr down        ; nach unten
  bra pl4
PL3: bsr up
PL4: cmp.b #lamiga,$bfec01
  bne PL5    ; linke Amigataste ?
  bsr lam    ; Ecke links oben
PL5: cmp.b #ramiga,$bfec01
  bne PL6    ; rechte Amigataste ?
  bsr ram    ; Ecke rechts unten
PL6: cmp.b #ctrl,$bfec01
  bne Ploop  ; Ctrl-Taste ?
PLEnd: rts  ; nein - weiter machen
Right:
  move.l #2,d6; Offset Planezeiger 
  move.w Spalte,d0 
  addq.w #1,d0   ; neue Spalte
  cmp.w #XMax,d0 ; gr”áer XMax ?
  bge PLEnd    ; ja - nicht setzen
  ror.w #1,Maske ; Punktmaske 
  bcs r1         ; verschieben
  move.l #0,d6   ; Punkt im Wort !
r1: move.w d0,Spalte ; Spaltenpos.
  sub.w HScrCount,d0; - Scrollzahl
  cmp.w #320,d0  ;    = Grenze ?
  bne r2   ; nein - kein Scrolling
  add.w #1,HScrCount ; Scrollz„hl.
  bsr Scrollright ; erh”hen und
  r2: bra set         ; fertig
Left:
  move.l #-2,d6  
  move.w Spalte,d0
  subq.w #1,d0
  bmi PLEnd
  rol.w #1,Maske
  bcs l1
  move.l #0,d6
l1: move.w d0,Spalte
  sub.w HScrCount,d0
  bpl l2
  sub.w #1,HScrCount
  bsr Scrollleft
l2: bra set
up:
  move.l #-Xmax/8,d6
  move.w Zeile,d0
  subq.w #1,d0
  bmi PLEnd
  move.w d0,Zeile
  sub.w VScrCount,d0
  bpl u1
  subq.w #1,VScrCount
  jsr WaitExecInt
  move.l #-XMax/8,d0 ; Bitplane-
  bsr AddPlaneTop ; zeiger in 
u1: bra set     ; Copperliste 
             ; um eins vermindern
down:
  move.l #XMax/8,d6
  move.w Zeile,d0
  addq.w #1,d0
  cmp.w #YMax,d0
  bge PLEnd
  move.w d0,Zeile
  sub.w VScrCount,d0
  cmp.w #256,d0
  bne set
  addq.w #1,VScrCount
  jsr WaitExecInt
  move.l #XMax/8,d0 ; Bitplane-
  bsr AddPlaneTop ; zeiger in 
        ; Copperliste vermindern
set:
  move.l #0,d1
  move.l SpritePtr,a0
  move.w Zeile,d0 ; akt. Zeile
  sub.w VScrCount,d0 ; - Scrollzahl
  add.w #$2b,d0   ; + Spriteoffset
  move.w d0,d2    ; = VSTART
  move.b d0,(a0) ; in Spritestrukt.
  lsr.w #8,d0  ; Bit 8 holen
  lsr.w #1,d0
  roxl.b #1,d1 ; und merken
  add.w #11,d2    ; + Spritel„nge
  move.b d2,2(a0) ; = VSTOP
  lsr.w #8,d2  ; Bit 8 holen
  lsr.w #1,d2
  roxl.b #1,d1 ; und merken
  move.w Spalte,d0 ; akt. Zeile
  sub.w HScrCount,d0; - Scrollzahl
  add.w #$3c*2,d0 ; + Spriteoffset
  lsr.w #1,d0  ; Bit 0 holen
  roxl.b #1,d1 ; und merken
  move.b d0,1(a0) ; HSTART
  move.b d1,3(a0) ; die gemerkten
                  ; Bits setzen
  add.l d6,a4 ; Planezeiger + Offs
  btst #6,PRA ; linke Maustaste ?
  bne noset   ; nein - kein Set
  move.w (a4),d0 ; Planewert holen
  or.w Maske,d0 ; OR mit Maske
  move.w d0,(a4) ; zurck in Plane
noset: move.l #200,d0
sloop: subq.l #1,d0 ; Verz”gerung
  bne sloop
  rts
WaitExecInt: ; wartet auf Raster-
  move.l CC+VPOSR,d0 ; strahlpos.
  and.l #$0001ff00,d0 ; gr”áer
  cmp.l #$00001000,d0 ; Zeile 16
  blt.s WaitExecInt
  rts
Scrollright:
  bsr WaitExecInt ; warten 
  sub.w #$0011,Delay ; Z„hler
  bpl sr1 ; fr verz”gerte Anzeige
  move.w #$00ff,Delay ; der Plane
  move.l #2,d0 ; Planezeiger in
  bsr AddPlaneTop ; Copperliste +2
sr1: move.w Delay,CC+BPLCON1
  rts ; Delay setzen
Scrollleft:
  bsr WaitExecInt
  add.w #$0011,Delay
  cmp.w #$0110,Delay
  blt sl1
  move.w #$0,Delay
  move.l #-2,d0 ; Planezeiger in  
  bsr AddPlaneTop ; Copperliste -2
sl1: move.w Delay,CC+BPLCON1 
  rts
AddPlaneTop:
  move.l UCopList,a0; Planezeiger 
  move.l 2(a0),d1 ; HI in der
  move.w 6(a0),d1 ; LO CopperList
  add.l d1,d0   ; + Offset
  move.w d0,6(a0) ; LO  
  lsr.l #8,d0     
  lsr.l #8,d0     ; HI  und wieder
  move.w d0,2(a0) ;     zurck
  rts
lAm:
  move.w #rot,CC+COLOR0 ; Spalte,
  move.w Spalte,lSpalte ; Zeile
  move.w Zeile,lZeile ; und akt.
  move.l a4,d0 ; Adresse in der
  and.l #$0003ffff,d0 ; Plane 
  move.l d0,lPPtr     ; merken
lAmEnde: rts
rAM:
  tst.l lPptr ; linke Ecke nicht
  beq lAMEnde; gesetzt? -> fertig
  move.w Spalte,rSpalte
  move.w Zeile,rZeile
  move.l a4,d0
  and.l #$0003ffff,d0
  move.l d0,rPPtr ; rechte Ecke
  cmp.l lPPtr,d0 ; kleiner als
  blt LAmEnde ; linke ? -> fertig
  move.l lPPtr,a0 ; Adresse Ecke
  move.l a0,CC+BLTAPTH ; links
  move.l a0,CC+BLTDPTH ; oben
  move.w #$090f,CC+BLTCON0 ; LF-
  move.w #0,CC+BLTCON1     ; Code
  move.w rZeile,d0 ; H”he des
  sub.w lZeile,d0 ; Blitterfenster
  asl.w #6,d0  ; nach Bit 6 bis 15
  move.w rSpalte,d1 ; Breite des
  sub.w lSpalte,d1  ; Fensters
  add.w #16,d1   ; in Worte
  lsr.w #4,d1    ; umrechnen
  or.w d1,d0     
  move.w #XMax/16,d3 ; Modulo ist
  sub.w d1,d3 ; von der Breite des
  asl.w #1,d3 ; Fensters abh„ngig
  move.w d3,CC+BLTAMOD ; Blitter-
  move.w d3,CC+BLTDMOD ; register
  move.w d0,CC+BLTSIZE ; setzen
  move.l #0,lPPtr ; linke Ecke l”-
  move.w #schwarz,CC+COLOR0; schen
  rts
