diff --git a/028.game2/Makefile b/028.game2/Makefile
new file mode 100644
index 0000000..1313a27
--- /dev/null
+++ b/028.game2/Makefile
@@ -0,0 +1,54 @@
+EXAMPLE_NAME=game1
+
+# userstack used by bootblock
+USERSTACK_ADDRESS=7fffc
+# if you change this you must also change link.script.x
+BASE_ADDRESS=4000
+# note: this must be high enough not to conflict with MFMbufE
+
+NUM_COLORS=8
+
+BOOTBLOCK_ASM=alpine_bootblock.s
+OBJS=out/init.o out/utils.o out/image.o out/blit.o
+
+#IMAGES=gigi_full.png
+#IMAGEDATA=$(addprefix out/, $(IMAGES:.png=.bin))
+#SIZEDIMAGEDATA=$(addprefix out/, $(IMAGES:.png=.sized.png))
+
+TILEMAPS=foreground.png background.png
+TILEMAPDATA=$(addprefix out/, $(TILEMAPS:.png=.bin))
+
+VASM_EXTRA_ARGS=-DNUM_COLORS=$(NUM_COLORS)
+
+#SYMBOL_INFO=-M
+LINKER_OPTIONS=-T link.script.x
+
+include ../shared/base.mk
+
+
+#out/%.sized.png: ../assets/%.png
+# $(RESIZE) --width=352 --height=256 --blur=0.75 --input=$< --output=$@
+
+out/%.bin: out/%.sized.png
+ $(IMAGECON) --input $< $(IMAGECON_ARGS) --quantize --colors $(NUM_COLORS) --output-bitplanes --output-palette-asm --output-grey-palette --output-palette $(DITHER) --output out/$*
+
+out/foreground.bin: assets/tilemap.png
+ $(IMAGECON) --use-palette=assets/foreground.pal --input $< $(IMAGECON_ARGS) --colors $(NUM_COLORS) --output-bitplanes --output-palette --full-color-palette-file --output-palette-asm --output-grey-palette --output-palette --output-png --output out/foreground
+
+out/background.bin: assets/tilemap.png
+ $(IMAGECON) --use-palette=assets/background.pal --input $< $(IMAGECON_ARGS) --colors $(NUM_COLORS) --output-bitplanes --output-palette --full-color-palette-file --output-palette-asm --output-grey-palette --output-palette --output-png --output out/background
+
+out/tilemap-palette.s: assets/tilemap.png
+ $(IMAGECON) --use-palette=assets/palette.pal --full-color-palette-file --input=assets/tilemap.png --output-palette-asm --output=out/tilemap
+
+out/foreground-map.s: foreground.tmx
+ ../tools/mapgen/out/mapgen --depth=3 --input=foreground.tmx
+ mv foreground-map.s out
+
+out/background-map.s: background.tmx
+ ../tools/mapgen/out/mapgen --depth=3 --input=background.tmx
+ mv background-map.s out
+
+out/blit.o: constants.i macros.i
+out/main.o: out/background-map.s out/foreground-map.s $(TILEMAPDATA) $(IMAGEDATA) constants.i macros.i Makefile link.script.x assets/palette.pal out/tilemap-palette.s
+out/init.o: constants.i Makefile
\ No newline at end of file
diff --git a/028.game2/README.md b/028.game2/README.md
new file mode 100644
index 0000000..0efad5c
--- /dev/null
+++ b/028.game2/README.md
@@ -0,0 +1,13 @@
+first simple game
+=================
+
+screenshot
+----------
+
+
+
+
+try it
+------
+ * [Download disk image](bin/game1.adf?raw=true)
+ * Run in SAE
diff --git a/028.game2/alpine_bootblock.s b/028.game2/alpine_bootblock.s
new file mode 100644
index 0000000..1953463
--- /dev/null
+++ b/028.game2/alpine_bootblock.s
@@ -0,0 +1,352 @@
+*** hardware trackloader bootblock
+*** original BootLoader.S by Photon ;NOTE: PC-relative code is PREFERRED.
+*** see http://coppershade.org/asmskool/SOURCES/Photon-snippets/DDE5-BootLoader.S
+*** this version hacked by alpine9000
+
+ include "../include/registers.i"
+
+LoaderVars equ $100 ;Useful variables, see CPUinfo:
+Loader equ $120 ;start of load script
+
+MyUserStack equ USERSTACK_ADDRESS ;SSP is at a safe place, but set user
+ ;stack.
+
+MFMsync equ $4489 ;AmigaDOS standard sync marker.
+MFMlen equ 12980 ;Legacy trackdata read length in bytes
+
+ShortWt:MACRO ;CPU-independent nop;nop replacement
+ tst.w (a6)
+ ENDM
+
+ *** Boot Block starts here ***
+
+Boot: dc.b 'DOS',0
+ dc.l 0,880
+
+BootCode: ;gathers some data, turns off OS, copies itself to $100
+
+ *--- Fetch system info ---*
+
+ move.l 4.w,a6 ;execbase (will soon be destroyed)
+ move.l 294(a6),d4 ;CPUinfo in lowest byte for your use.
+ sub.l a4,a4 ;VBR will always be 0 when booting
+ ;from floppy. No GetVBR needed.
+ *--- Fastmem available? ---*
+
+ if 1
+ move.l #$20004,d1 ;fast+largest
+ else
+ move.l #$20002,d1 ;chip+largest
+ endif
+ jsr -216(a6) ;AvailMem()
+ move.l d0,d5
+
+ sub.l #2048,d5 ;leave room for stacks to grow
+ moveq #4,d1
+ jsr -198(a6) ;AllocMem()
+ and.l #-8,d0
+ move.l d0,a5 ;Start Address
+
+ *--- OS off ---* ;you're nice'n all, but now you die.
+
+ lea $dff002,a6 ;Loader uses this custom base addr
+
+ tst.w (a6) ;wait out blitter
+.wblit: btst #6,(a6)
+ bne.s .wblit
+
+ move.l #$7fff7fff,d1
+ move.l d1,$9a-2(a6) ;disable interrupts & req
+ move.w d1,$9c-2(a6) ;play it again Sam
+ sub.w #$20,d1 ;don't affect Sprite DMA until Vblank
+ move.w d1,$96-2(a6) ;disable DMA
+
+ lea MyUserStack,a7 ;some safe place compatible with
+ ;platform requirements
+ *--- Copy rest of code/data to fixed address ---*
+
+ lea CopyStart(PC),a0
+ lea (LoaderVars).w,a1
+ moveq #(BootE-CopyStart)/8,d2
+.copyl: move.l (a0)+,(a1)+
+ move.l (a0)+,(a1)+
+ dbf d2,.copyl
+ JMP (Loader).w ;Info from Exec passed in 4 registers
+
+******************** $100.w ********************
+
+CopyStart:
+
+CPUinfo: dc.l 0 ;$100
+FastMemSize: dc.l 0 ;$104
+SysVBR: dc.l 0 ;$108
+FastMemStart: dc.l 0 ;$10c
+
+MFMcyl: dc.w 0
+MFMhead: dc.w 0
+MFMdrv: dc.w 0
+MFMchk: dc.l 0
+
+ dc.w 0 ;padding to $120
+ dc.w 0 ;
+ dc.w 0 ;
+
+LoadScript: ;At $120, sysinfo in 4 regs, a6=$dff002
+ lea CPUinfo(PC),a3 ;Use this for PC-rel in a pinch.
+ movem.l d4/d5/a4/a5,(a3)
+ bsr.s WaitEOF
+ lea NullCop(PC),a0
+ move.l a0,$80-2(a6) ;blank copper
+ move.w #$87d0,$96-2(a6) ;enable DMA (sprites enabled when used)
+
+ *--- load first part ---*
+
+ lea BASE_ADDRESS,a0 ; main entry point
+
+ if 1
+ moveq #2,d0 ;from sector 2
+ move.w #-1,d1 ;num sectors, - ==Step0
+ jsr LoadMFMB
+
+ move.l 4(a0),d1
+ add.l #512,d1
+ lsr.l #6,d1
+ lsr.l #3,d1
+ moveq #2,d0 ;from sector 2
+ jsr LoadMFMB
+
+ lea $dff000,a6 ;restore plain custombase addr for demo
+
+ move.l (a0),a0
+ jmp (a0) ; -> main entry point
+
+ else
+
+ -moveq #2,d0 ;from sector 2
+ move.w #-((mainEnd-mainStart)/512),d1;num sectors, - ==Step0
+ jsr LoadMFMB
+
+ jmp (a0) ; -> main entry point
+
+ endif
+
+ *** MFMLoader.S by Photon *** ;requires a6=$dff002
+
+WaitEOF:
+ btst #0,5-2(a6)
+ beq.s WaitEOF
+.w1: cmp.b #$37,6-2(a6)
+ bne.s .w1
+.w2: cmp.b #$37,6-2(a6) ;wait for last PAL line, $138
+ beq.s .w2
+ rts
+
+LoadMFMB: ;loadsectors.a0=dst,d0=startsec.W,d1=nrsecs.W(-=Step0)
+ MOVEM.L D0-D7/A0-A6,-(SP)
+ lea $bfd100,a4
+ bsr MotorOn
+ tst.w d1 ;if neg length,then Step0 first
+ bpl.s .NoSt0
+ neg.w d1
+.St0: btst #4,$f01(a4) ;head on cyl 0?
+ beq.s .Rdy0
+ bsr.s StepOut
+ bra.s .St0
+.Rdy0: lea MFMcyl(PC),a1
+ clr.w (a1)
+.NoSt0: and.l #$ffff,d0
+ divu #22,d0 ;startcyl
+ sub.w MFMcyl(PC),d0 ;delta-step
+ beq.s .StRdy
+ bmi.s .StOut
+ subq.w #1,d0
+.StIn: bsr.s StepIn
+ dbf d0,.StIn
+ bra.s .StRdy
+ not.w d0 ;=neg+sub#1
+.StOut: bsr.s StepOut
+ dbf d0,.StIn
+.StRdy: swap d0 ;startsec within cyl
+ cmp.w #11,d0
+ blt.s .Head0
+ sub.w #11,d0
+ bra.s .Head1
+.Head0: bset #2,(a4)
+ lea MFMhead(PC),a1
+ clr.w (a1)
+ bsr LoadTrak ;read track+decode
+ beq.s .End
+.Head1: bclr #2,(a4) ;Head 1
+ lea MFMhead(PC),a1
+ move.w #1,(a1)
+ bsr LoadTrak ;read track+decode
+ beq.s .End
+ bsr.s StepIn ;1 cyl forward
+ bra.s .Head0
+.End: bsr.s MotorOff
+ MOVEM.L (SP)+,D0-D7/A0-A6
+ RTS
+
+StepOut:
+ bset #1,(a4)
+ lea MFMcyl(PC),a1
+ subq.w #1,(a1)
+ ShortWt
+ bclr #0,(a4)
+ ShortWt
+ bset #0,(a4)
+ bsr.s StepWt
+ RTS
+
+StepIn:
+ bclr #1,(a4)
+ lea MFMcyl(PC),a1
+ addq.w #1,(a1)
+ ShortWt
+ bclr #0,(a4)
+ ShortWt
+ bset #0,(a4)
+ bsr.s StepWt
+ RTS
+
+StepWt:
+ moveq #67,d6 ;wait >3 ms
+LeaveLine:
+.loop1: move.b 6-2(a6),d7
+.loop2: cmp.b 6-2(a6),d7
+ beq.s .loop2
+ dbf d6,.loop1
+ RTS
+
+MotorOn:
+ move.w MFMdrv(PC),d7
+ addq.w #3,d7
+ or.b #$78,(a4)
+ bset d7,(a4)
+ ShortWt
+ bclr #7,(a4) ;turns motor on
+ ShortWt
+ bclr d7,(a4)
+ ShortWt
+.DiskR: btst #5,$f01(a4) ;wait until motor running
+ bne.s .DiskR
+ RTS
+
+MotorOff:
+ move.w MFMdrv(PC),d7
+ addq.w #3,d7
+ bset d7,(a4)
+ ShortWt
+ bset #7,(a4)
+ ShortWt
+ bclr d7,(a4)
+ RTS
+
+LoadTrak: ;loadtrack+decode.a0=dst,d0=secoffs,d1=secsleft
+ MOVE.W D0,-(SP)
+ MOVE.W D1,-(SP)
+ ;; lea (MFMbuf).w,a1
+ lea (MFMbuf),a1
+ move.w #2,$9c-2(a6) ;Clr Req
+ move.l a1,$20-2(a6)
+ move.w #$8210,$96-2(a6) ;DskEna
+ move.w #MFMsync,$7e-2(a6)
+ move.w #$9500,$9e-2(a6)
+ move.w #$4000,$24-2(a6)
+ move.w #$8000+MFMlen/2,$24-2(a6);DskLen(12980)+DmaEn
+ move.w #$8000+MFMlen/2,$24-2(a6);start reading MFMdata
+.Wrdy:
+ btst #1,$1f-2(a6) ;wait until data read
+ beq.s .Wrdy
+ move.w d0,d2
+ add.w d1,d2 ;highest sec# (d0=lowest)
+ cmp.w #11,d2
+ ble.s .NoOvr
+ moveq #11,d2
+.NoOvr: sub.w d0,d2 ;nrsecs
+ move.l #$55555555,d3 ;and-const
+ move.w d2,d1
+ subq.w #1,d1 ;loopctr
+.FindS: cmp.w #MFMsync,(a1)+ ;search for a sync word
+ bne.s .FindS
+ cmp.b (a1),d3 ;search for 0-nibble
+ bne.s .FindS
+ move.l (a1)+,d4 ;decode fmtbyte/trk#,sec#,eow#
+ move.l (a1)+,d5
+ and.w d3,d4
+ and.w d3,d5
+ add.w d4,d4
+ or.w d5,d4
+ lsr.w #8,d4 ;sec#
+ sub.w d0,d4 ;do we want this sec?
+ bmi.s .Skip
+ cmp.w d2,d4
+ blt.s .DeCode
+.Skip: lea 48+1024(a1),a1 ;nope
+ bra.s .FindS
+.DeCode:lea 40(a1),a1 ;found a sec,skip unnecessary data
+ move.l a1,d6
+ lea MFMchk(PC),a1
+ clr.l (a1)
+ move.l d6,a1
+ move.l (a1)+,d6 ;decode data chksum.L
+ move.l (a1)+,d5
+ and.l d3,d6
+ and.l d3,d5
+ add.l d6,d6
+ or.l d5,d6 ;chksum
+ lea 512(a1),a2
+ add.w d4,d4 ;x512
+ lsl.w #8,d4
+ lea (a0,d4.w),a3 ;dest addr for this sec
+ moveq #127,d7
+.DClup: move.l (a1)+,d4
+ move.l (a2)+,d5
+ and.l d3,d4
+ and.l d3,d5
+ eor.l d4,d6 ;EOR with checksum
+ eor.l d5,d6 ;EOR with checksum
+ add.l d4,d4
+ or.l d5,d4
+ move.l d4,(a3)+
+ dbf d7,.DClup ;chksum should now be 0 if correct
+ lea MFMchk(PC),a1
+ or.l d6,(a1) ;or with track total chksum
+ move.l a2,a1
+ dbf d1,.FindS ;decode next sec
+ MOVE.W (SP)+,D1
+ MOVE.W (SP)+,D0
+ move.l MFMchk(PC),d3 ;track total chksum OK?
+ bne LoadTrak ;no,retry
+ moveq #0,d0 ;set to start of track
+ move.w d2,d3
+ add.w d3,d3
+ lsl.w #8,d3
+ add.w d3,a0
+ sub.w d2,d1 ;sub #secs loaded
+ RTS
+
+NullCop:
+ dc.w $1fc,0
+ dc.w $100,$0200
+ dc.w $96,$0020 ;ensure sprite DMA is off until needed
+ dc.w $ffdf,$fffe
+ dc.l -2
+BootE:
+
+ *** Boot Block ends here ***
+
+ dc.b "BootLoader by Photon/Scoopex"
+ ;pad bootblock to correct size
+ cnop 0,1024
+
+;MFMbuf is placed here after bootblock end, $3c0.w or so when copied.
+MFMbuf equ LoaderVars+(BootE-CopyStart)
+MFMbufE equ MFMbuf+MFMlen ;lowest free address. $372e for a full bootblock.
+
+mainStart:
+ incbin "out/main.bin"
+ cnop 0,512
+mainEnd:
+ end
+
diff --git a/028.game2/assets/background.pal b/028.game2/assets/background.pal
new file mode 100644
index 0000000..1ec1785
--- /dev/null
+++ b/028.game2/assets/background.pal
@@ -0,0 +1,8 @@
+000 000 014 255
+029 192 255 255
+121 235 255 255
+071 174 192 255
+213 213 213 255
+210 000 039 255
+154 154 154 255
+000 000 000 000
\ No newline at end of file
diff --git a/028.game2/assets/foreground.pal b/028.game2/assets/foreground.pal
new file mode 100644
index 0000000..5e4116a
--- /dev/null
+++ b/028.game2/assets/foreground.pal
@@ -0,0 +1,8 @@
+000 000 000 255
+082 000 015 255
+133 000 026 255
+210 063 006 255
+211 116 039 255
+253 174 017 255
+233 216 100 255
+016 132 233 255
\ No newline at end of file
diff --git a/028.game2/assets/foreground.png b/028.game2/assets/foreground.png
new file mode 100644
index 0000000..e45df48
Binary files /dev/null and b/028.game2/assets/foreground.png differ
diff --git a/028.game2/assets/palette.pal b/028.game2/assets/palette.pal
new file mode 100644
index 0000000..a1cacfb
--- /dev/null
+++ b/028.game2/assets/palette.pal
@@ -0,0 +1,25 @@
+000 000 000 255
+082 000 015 255
+133 000 026 255
+210 063 006 255
+211 116 039 255
+253 174 017 255
+233 216 100 255
+016 132 233 255
+000 000 014 255
+029 192 255 255
+121 235 255 255
+071 174 192 255
+213 213 213 255
+210 000 039 255
+154 154 154 255
+000 000 000 000
+232 174 100 255
+252 114 100 255
+171 049 027 255
+004 050 117 255
+020 155 173 255
+030 236 255 255
+252 115 009 255
+255 255 011 255
+255 255 255 255
diff --git a/028.game2/assets/tilemap.png b/028.game2/assets/tilemap.png
new file mode 100644
index 0000000..0f8ff51
Binary files /dev/null and b/028.game2/assets/tilemap.png differ
diff --git a/028.game2/background.tmx b/028.game2/background.tmx
new file mode 100644
index 0000000..459376b
--- /dev/null
+++ b/028.game2/background.tmx
@@ -0,0 +1,11 @@
+
+
diff --git a/028.game2/blit.s b/028.game2/blit.s
new file mode 100644
index 0000000..5254acc
--- /dev/null
+++ b/028.game2/blit.s
@@ -0,0 +1,161 @@
+ include "includes.i"
+
+ xdef BlitFillColor
+ xdef BlitScroll
+ xdef BlitTile
+ xref BlueFill
+
+;; A(mask) B(bob) C(bg) D(dest)
+;; - - - -
+;; 0 0 0 0
+;; 0 0 1 1
+;; 0 1 0 0
+;; 0 1 1 1
+;; 1 0 0 0
+;; 1 0 1 0
+;; 1 1 0 1
+;; 1 1 1 1
+
+BlitFillColor:
+ ;; kills a0,d2,d3,d5,d5
+ ;; a0 - bitplane
+ ;; d0 - color#
+ ;; d1 - height
+ ;; d2 - ypos
+
+ movem.l d2-d5/a0,-(sp)
+ mulu.w #BITPLANE_WIDTH_BYTES*SCREEN_BIT_DEPTH,d2
+ add.l d2,a0
+ move.b #0,d3 ; bitplane #
+.loop:
+ move.w d1,d4
+ btst d3,d0 ; is the color's bit set in this plane?
+ beq .zero
+ move.w #BC0F_DEST|$FF,d5 ; yes ? all ones
+ bra .doblit
+.zero
+ move.w #BC0F_DEST|$0,d5 ; no ? all zeros
+.doblit
+ WaitBlitter
+
+ move.w #0,BLTCON1(A6)
+ move.w d5,BLTCON0(A6)
+ move.w #BITPLANE_WIDTH_BYTES*(SCREEN_BIT_DEPTH-1),BLTDMOD(a6)
+ move.l a0,BLTDPTH(a6)
+
+ lsl.w #6,d4
+ ori.w #BITPLANE_WIDTH_WORDS,d4
+ move.w d4,BLTSIZE(a6)
+ add.b #1,d3
+ add.w #BITPLANE_WIDTH_BYTES,a0
+ cmp.b #SCREEN_BIT_DEPTH,d3 ; all planes for a single line done ?
+ bne .loop ; no ? do the next plane
+
+ movem.l (sp)+,d2-d5/a0
+ rts
+
+
+
+_BlitScroll:
+ ;; left scroll a screen wide region
+ ;; a0 - dest bitplane pointer
+ ;; a1 - source bitplane pointer
+ ;; d0 - number of pixels to left shift on blit
+ ;; d1 - height in pixels
+ ;; d2 - y destination in pixels
+
+ movem.l d0-d2/a0-a1,-(sp)
+ add.l d1,d2 ; point to end of data for descending mode
+ mulu.w #BITPLANE_WIDTH_BYTES*SCREEN_BIT_DEPTH,d2
+ add.l d2,a0 ; end of dest bitplane
+ add.l d2,a1 ; end of source bitplane
+
+ WaitBlitter
+
+ swap d0 ; lsl.l #ASHIFTSHIFT,d0
+ lsr.l #4,d0 ; d0 has ASHIFTSHIFT bits set
+ ori.w #BC1F_DESC,d0 ; BLTCON1 value. shift and descending mode
+ move.w d0,BLTCON1(a6) ;
+ and.w #$f000,d0 ; keep the shift, remove the rest
+ ori.w #BC0F_SRCB|BC0F_SRCC|BC0F_DEST|$ca,d0 ; BLTCON0 value. shift, dma and logic function
+ move.w d0,BLTCON0(a6)
+
+ move.w #0,BLTBMOD(a6) ; no modulo, blitting full width data
+ move.w #0,BLTCMOD(a6) ;
+ move.w #0,BLTDMOD(a6) ;
+ move.l a1,BLTBPTH(a6) ; source
+ move.l a1,BLTCPTH(a6) ; background
+ move.l a0,BLTDPTH(a6) ; dest
+ move.w #$0000,BLTAFWM(a6) ; A DMA is disabled, but the channel is still used in the logic function
+ move.w #$ffff,BLTALWM(a6) ; as we use it for masking
+ move.w #$ffff,BLTADAT(a6) ; preload source mask so only BLTA?WM mask is used
+
+ mulu.w #SCREEN_BIT_DEPTH,d1
+ lsl.w #6,d1
+ ori.w #BITPLANE_WIDTH_WORDS,d1
+ move.w d1,BLTSIZE(a6)
+
+ movem.l (sp)+,d0-d2/a0-a1
+ rts
+
+
+
+BlitTile:
+ ;; a0 - dest bitplane pointer
+ ;; a1 - source tile pointer
+ ;; d2 - y tile index
+
+ WaitBlitter
+ movem.l d2/a0,-(sp)
+ move.w #0,BLTCON1(a6) ;
+ move.w #BC0F_SRCA|BC0F_DEST|$f0,BLTCON0(a6)
+
+ move.w #TILEMAP_WIDTH_BYTES-2,BLTAMOD(a6)
+ move.w #BITPLANE_WIDTH_BYTES-2,BLTDMOD(a6) ;
+
+ mulu.w #BITPLANE_WIDTH_BYTES*SCREEN_BIT_DEPTH*16,d2
+ add.l d2,a0
+ move.l a1,BLTAPTH(a6) ; source
+ move.l a0,BLTDPTH(a6) ; dest
+ move.w #$ffff,BLTAFWM(a6)
+ move.w #$ffff,BLTALWM(a6)
+ move.w #(16*SCREEN_BIT_DEPTH)<<6|(1),BLTSIZE(a6) ;rectangle size, starts blit
+ movem.l (sp)+,d2/a0
+ rts
+
+
+BlueFill:
+ movem.l d0-a6,-(sp)
+ ;; a0 - bitplane
+ ;; d0 - color#
+ ;; d1 - height
+ ;; d2 - ypos
+ move.l foregroundOffscreen,a0
+ move.l #0,d0
+ move.l #256,d1
+ move.l #0,d2
+ jsr BlitFillColor
+ jsr WaitVerticalBlank
+ jsr SwitchBuffers
+ move.l foregroundOffscreen,a0
+ move.l #0,d0
+ move.l #256,d1
+ move.l #0,d2
+ jsr BlitFillColor
+ jsr WaitVerticalBlank
+ jsr SwitchBuffers
+ move.l backgroundOffscreen,a0
+ move.l #0,d0
+ move.l #256,d1
+ move.l #0,d2
+ jsr BlitFillColor
+ jsr WaitVerticalBlank
+ jsr SwitchBuffers
+ move.l backgroundOffscreen,a0
+ move.l #0,d0
+ move.l #256,d1
+ move.l #0,d2
+ jsr BlitFillColor
+ movem.l (sp)+,d0-a6
+ rts
+
diff --git a/028.game2/blitchar.s b/028.game2/blitchar.s
new file mode 100644
index 0000000..2e2ac7f
--- /dev/null
+++ b/028.game2/blitchar.s
@@ -0,0 +1,87 @@
+ include "includes.i"
+
+ xdef BlitChar8
+
+DESCENDING equ 1
+BLIT_LF_MINTERM equ $ca ; cookie cut
+BLIT_WIDTH_WORDS equ 1 ; blit 2 words to allow shifting
+BLIT_WIDTH_BYTES equ BLIT_WIDTH_WORDS*2
+FONTMAP_WIDTH_BYTES equ 32
+
+ if MASKED_FONT==1
+BLTCON0_VALUE equ BC0F_SRCA|BC0F_SRCB|BC0F_SRCC|BC0F_DEST|BLIT_LF_MINTERM
+ else
+BLTCON0_VALUE equ BC0F_SRCB|BC0F_SRCC|BC0F_DEST|BLIT_LF_MINTERM
+ endif
+
+BlitChar8:
+ ;; a0 - bitplane
+ ;; d0 - xpos
+ ;; d1 - ypos
+ ;; d2 - char
+ movem.l d0-d3/a0-a2,-(sp)
+ mulu.w #BITPLANE_WIDTH_BYTES*SCREEN_BIT_DEPTH,d1 ; ypos bytes
+ lea font(pc),a1 ; font pointer
+
+ sub.w #'!',d2 ; index = char - '!'
+ move.w d2,d3
+ lsr.w #5,d3 ; char / 32 = fontmap line
+ andi.w #$1f,d2 ; char index in line (char index - start of line index)
+ add.l #1,d3 ; while we have a weird font image, '!' starts on second line
+ mulu.w #FONTMAP_WIDTH_BYTES*SCREEN_BIT_DEPTH*FONT_HEIGHT,d3 ; d3 *= #FONTMAP_WIDTH_BYTES*SCREEN_BIT_DEPTH*FONT_HEIGHT
+
+ add.l #(FONT_HEIGHT*SCREEN_BIT_DEPTH*FONTMAP_WIDTH_BYTES)-FONTMAP_WIDTH_BYTES+0,a1 ; last word - descending mode
+
+ add.w d3,a1 ; add y offset in lines to font address
+ add.w d2,a1 ; add offset into font
+ lsr.w #3,d0 ; d0 = xpos bytes
+
+ add.l d0,a0 ; dest += XPOS_BYTES
+ add.l d1,a0 ; dest += YPOS_BYTES
+ add.l #(FONT_HEIGHT*SCREEN_BIT_DEPTH*BITPLANE_WIDTH_BYTES)-BITPLANE_WIDTH_BYTES+0,a0 ; last word - descending mode
+
+ WaitBlitter
+
+ if MASKED_FONT==1
+ move.w #FONTMAP_WIDTH_BYTES-BLIT_WIDTH_BYTES,BLTAMOD(a6) ; A modulo (only used for masked version)
+ endif
+ move.w #FONTMAP_WIDTH_BYTES-BLIT_WIDTH_BYTES,BLTBMOD(a6) ; B modulo
+ move.w #BITPLANE_WIDTH_BYTES-BLIT_WIDTH_BYTES,BLTCMOD(a6) ; C modulo
+ move.w #BITPLANE_WIDTH_BYTES-BLIT_WIDTH_BYTES,BLTDMOD(a6) ; D modulo
+ move.w #$ffff,BLTAFWM(a6) ; don't mask first word
+
+
+ btst #0,d2 ; check if odd or even char
+ beq .evenChar ;
+.oddChar:
+ move.w #$00ff,BLTALWM(a6) ; select the second (odd) character in the word
+ move.w #BLTCON0_VALUE|$8000,BLTCON0(a6)
+ move.w #$8002,BLTCON1(a6) ; set the shift bits 12-15, bits 00-11 cleared
+ bra .continue
+.evenChar:
+ move.w #$FF00,BLTALWM(a6) ; select the first character in the word
+ move.w #BLTCON0_VALUE,BLTCON0(a6)
+ move.w #$2,BLTCON1(a6) ; set the shift bits 12-15, bits 00-11 cleared
+.continue:
+
+
+ move.l a1,BLTBPTH(a6) ; source bitplane
+
+ if MASKED_FONT==1
+ add.l #fontMask-font,a1
+ move.l a1,BLTAPTH(a6) ; mask bitplane
+ endif
+
+
+ move.l a0,BLTCPTH(a6) ; background top left corner
+ move.l a0,BLTDPTH(a6) ; destination top left corner
+
+ move.w #(FONT_HEIGHT*SCREEN_BIT_DEPTH)<<6|(BLIT_WIDTH_WORDS),BLTSIZE(a6) ;rectangle size, starts blit
+
+ movem.l (sp)+,d0-d3/a0-a2
+ rts
+
+font:
+ incbin "out/font8x8.bin"
+fontMask:
+ incbin "out/font8x8-mask.bin"
diff --git a/028.game2/constants.i b/028.game2/constants.i
new file mode 100644
index 0000000..6b58ae4
--- /dev/null
+++ b/028.game2/constants.i
@@ -0,0 +1,39 @@
+BACKGROUND_UPDATE_COUNT equ $3
+FOREGROUND_DELAY_BIT equ 0
+
+SCREEN_WIDTH equ 320
+SCREEN_HEIGHT equ 256
+SCREEN_WIDTH_BYTES equ (SCREEN_WIDTH/8)
+SCREEN_WIDTH_WORDS equ SCREEN_WIDTH_BYTES/2
+BITPLANE_WIDTH equ 352
+BITPLANE_WIDTH_BYTES equ BITPLANE_WIDTH/8
+BITPLANE_WIDTH_WORDS equ BITPLANE_WIDTH_BYTES/2
+TILEMAP_WIDTH equ 320
+TILEMAP_WIDTH_BYTES equ TILEMAP_WIDTH/8
+TILEMAP_WIDTH_WORDS equ TILEMAP_WIDTH_BYTES/2
+
+ if NUM_COLORS==64
+SCREEN_BIT_DEPTH equ 6
+ endif
+ if NUM_COLORS==32
+SCREEN_BIT_DEPTH equ 5
+ endif
+ if NUM_COLORS==16
+SCREEN_BIT_DEPTH equ 4
+ endif
+ if NUM_COLORS==8
+SCREEN_BIT_DEPTH equ 3
+ endif
+ if NUM_COLORS==4
+SCREEN_BIT_DEPTH equ 2
+ endif
+ if NUM_COLORS==2
+SCREEN_BIT_DEPTH equ 1
+ endif
+
+SCREEN_RES equ 8 ; 8=lo resolution, 4=hi resolution
+RASTER_X_START equ $81 ; hard coded coordinates from hardware manual
+RASTER_Y_START equ $2c
+RASTER_X_STOP equ RASTER_X_START+SCREEN_WIDTH
+RASTER_Y_STOP equ RASTER_Y_START+256
+IMAGESIZE equ BITPLANE_WIDTH_BYTES*SCREEN_BIT_DEPTH*SCREEN_HEIGHT
\ No newline at end of file
diff --git a/028.game2/copperlist.s b/028.game2/copperlist.s
new file mode 100644
index 0000000..861bad4
--- /dev/null
+++ b/028.game2/copperlist.s
@@ -0,0 +1,516 @@
+ dc.w $2c07,$fffe
+ dc.w COLOR01,$7dd
+ dc.w $2d07,$fffe
+ dc.w COLOR01,$9ec
+ dc.w $2e07,$fffe
+ dc.w COLOR01,$beb
+ dc.w $2f07,$fffe
+ dc.w COLOR01,$ce9
+ dc.w $3007,$fffe
+ dc.w COLOR01,$ed7
+ dc.w $3107,$fffe
+ dc.w COLOR01,$eb5
+ dc.w $3207,$fffe
+ dc.w COLOR01,$e93
+ dc.w $3307,$fffe
+ dc.w COLOR01,$d71
+ dc.w $3407,$fffe
+ dc.w COLOR01,$c50
+ dc.w $3507,$fffe
+ dc.w COLOR01,$a30
+ dc.w $3607,$fffe
+ dc.w COLOR01,$820
+ dc.w $3707,$fffe
+ dc.w COLOR01,$611
+ dc.w $3807,$fffe
+ dc.w COLOR01,$403
+ dc.w $3907,$fffe
+ dc.w COLOR01,$204
+ dc.w $3a07,$fffe
+ dc.w COLOR01,$116
+ dc.w $3b07,$fffe
+ dc.w COLOR01,$029
+ dc.w $3c07,$fffe
+ dc.w COLOR01,$04a
+ dc.w $3d07,$fffe
+ dc.w COLOR01,$16c
+ dc.w $3e07,$fffe
+ dc.w COLOR01,$28d
+ dc.w $3f07,$fffe
+ dc.w COLOR01,$3ae
+ dc.w $4007,$fffe
+ dc.w COLOR01,$5ce
+ dc.w $4107,$fffe
+ dc.w COLOR01,$7dd
+ dc.w $4207,$fffe
+ dc.w COLOR01,$9ec
+ dc.w $4307,$fffe
+ dc.w COLOR01,$beb
+ dc.w $4407,$fffe
+ dc.w COLOR01,$de9
+ dc.w $4507,$fffe
+ dc.w COLOR01,$ed6
+ dc.w $4607,$fffe
+ dc.w COLOR01,$eb4
+ dc.w $4707,$fffe
+ dc.w COLOR01,$e93
+ dc.w $4807,$fffe
+ dc.w COLOR01,$d71
+ dc.w $4907,$fffe
+ dc.w COLOR01,$c50
+ dc.w $4a07,$fffe
+ dc.w COLOR01,$a30
+ dc.w $4b07,$fffe
+ dc.w COLOR01,$820
+ dc.w $4c07,$fffe
+ dc.w COLOR01,$611
+ dc.w $4d07,$fffe
+ dc.w COLOR01,$403
+ dc.w $4e07,$fffe
+ dc.w COLOR01,$204
+ dc.w $4f07,$fffe
+ dc.w COLOR01,$117
+ dc.w $5007,$fffe
+ dc.w COLOR01,$029
+ dc.w $5107,$fffe
+ dc.w COLOR01,$04b
+ dc.w $5207,$fffe
+ dc.w COLOR01,$16c
+ dc.w $5307,$fffe
+ dc.w COLOR01,$28d
+ dc.w $5407,$fffe
+ dc.w COLOR01,$3ae
+ dc.w $5507,$fffe
+ dc.w COLOR01,$5ce
+ dc.w $5607,$fffe
+ dc.w COLOR01,$7dd
+ dc.w $5707,$fffe
+ dc.w COLOR01,$9ec
+ dc.w $5807,$fffe
+ dc.w COLOR01,$bea
+ dc.w $5907,$fffe
+ dc.w COLOR01,$de8
+ dc.w $5a07,$fffe
+ dc.w COLOR01,$ed6
+ dc.w $5b07,$fffe
+ dc.w COLOR01,$eb4
+ dc.w $5c07,$fffe
+ dc.w COLOR01,$e93
+ dc.w $5d07,$fffe
+ dc.w COLOR01,$d71
+ dc.w $5e07,$fffe
+ dc.w COLOR01,$c50
+ dc.w $5f07,$fffe
+ dc.w COLOR01,$a30
+ dc.w $6007,$fffe
+ dc.w COLOR01,$820
+ dc.w $6107,$fffe
+ dc.w COLOR01,$601
+ dc.w $6207,$fffe
+ dc.w COLOR01,$403
+ dc.w $6307,$fffe
+ dc.w COLOR01,$205
+ dc.w $6407,$fffe
+ dc.w COLOR01,$117
+ dc.w $6507,$fffe
+ dc.w COLOR01,$029
+ dc.w $6607,$fffe
+ dc.w COLOR01,$04b
+ dc.w $6707,$fffe
+ dc.w COLOR01,$16c
+ dc.w $6807,$fffe
+ dc.w COLOR01,$28d
+ dc.w $6907,$fffe
+ dc.w COLOR01,$3ae
+ dc.w $6a07,$fffe
+ dc.w COLOR01,$5ce
+ dc.w $6b07,$fffe
+ dc.w COLOR01,$7dd
+ dc.w $6c07,$fffe
+ dc.w COLOR01,$9ec
+ dc.w $6d07,$fffe
+ dc.w COLOR01,$bea
+ dc.w $6e07,$fffe
+ dc.w COLOR01,$de8
+ dc.w $6f07,$fffe
+ dc.w COLOR01,$ec6
+ dc.w $7007,$fffe
+ dc.w COLOR01,$eb4
+ dc.w $7107,$fffe
+ dc.w COLOR01,$e92
+ dc.w $7207,$fffe
+ dc.w COLOR01,$d71
+ dc.w $7307,$fffe
+ dc.w COLOR01,$b50
+ dc.w $7407,$fffe
+ dc.w COLOR01,$a30
+ dc.w $7507,$fffe
+ dc.w COLOR01,$810
+ dc.w $7607,$fffe
+ dc.w COLOR01,$601
+ dc.w $7707,$fffe
+ dc.w COLOR01,$403
+ dc.w $7807,$fffe
+ dc.w COLOR01,$205
+ dc.w $7907,$fffe
+ dc.w COLOR01,$117
+ dc.w $7a07,$fffe
+ dc.w COLOR01,$029
+ dc.w $7b07,$fffe
+ dc.w COLOR01,$04b
+ dc.w $7c07,$fffe
+ dc.w COLOR01,$16c
+ dc.w $7d07,$fffe
+ dc.w COLOR01,$28d
+ dc.w $7e07,$fffe
+ dc.w COLOR01,$3ae
+ dc.w $7f07,$fffe
+ dc.w COLOR01,$5ce
+ dc.w $8007,$fffe
+ dc.w COLOR01,$7dd
+ dc.w $8107,$fffe
+ dc.w COLOR01,$aec
+ dc.w $8207,$fffe
+ dc.w COLOR01,$bea
+ dc.w $8307,$fffe
+ dc.w COLOR01,$dd8
+ dc.w $8407,$fffe
+ dc.w COLOR01,$ec6
+ dc.w $8507,$fffe
+ dc.w COLOR01,$eb4
+ dc.w $8607,$fffe
+ dc.w COLOR01,$e92
+ dc.w $8707,$fffe
+ dc.w COLOR01,$d71
+ dc.w $8807,$fffe
+ dc.w COLOR01,$b50
+ dc.w $8907,$fffe
+ dc.w COLOR01,$a30
+ dc.w $8a07,$fffe
+ dc.w COLOR01,$810
+ dc.w $8b07,$fffe
+ dc.w COLOR01,$501
+ dc.w $8c07,$fffe
+ dc.w COLOR01,$303
+ dc.w $8d07,$fffe
+ dc.w COLOR01,$205
+ dc.w $8e07,$fffe
+ dc.w COLOR01,$117
+ dc.w $8f07,$fffe
+ dc.w COLOR01,$029
+ dc.w $9007,$fffe
+ dc.w COLOR01,$04b
+ dc.w $9107,$fffe
+ dc.w COLOR01,$16c
+ dc.w $9207,$fffe
+ dc.w COLOR01,$28d
+ dc.w $9307,$fffe
+ dc.w COLOR01,$4ae
+ dc.w $9407,$fffe
+ dc.w COLOR01,$6ce
+ dc.w $9507,$fffe
+ dc.w COLOR01,$8dd
+ dc.w $9607,$fffe
+ dc.w COLOR01,$aec
+ dc.w $9707,$fffe
+ dc.w COLOR01,$bea
+ dc.w $9807,$fffe
+ dc.w COLOR01,$dd8
+ dc.w $9907,$fffe
+ dc.w COLOR01,$ec6
+ dc.w $9a07,$fffe
+ dc.w COLOR01,$eb4
+ dc.w $9b07,$fffe
+ dc.w COLOR01,$e92
+ dc.w $9c07,$fffe
+ dc.w COLOR01,$d71
+ dc.w $9d07,$fffe
+ dc.w COLOR01,$b50
+ dc.w $9e07,$fffe
+ dc.w COLOR01,$930
+ dc.w $9f07,$fffe
+ dc.w COLOR01,$710
+ dc.w $a007,$fffe
+ dc.w COLOR01,$502
+ dc.w $a107,$fffe
+ dc.w COLOR01,$303
+ dc.w $a207,$fffe
+ dc.w COLOR01,$205
+ dc.w $a307,$fffe
+ dc.w COLOR01,$117
+ dc.w $a407,$fffe
+ dc.w COLOR01,$029
+ dc.w $a507,$fffe
+ dc.w COLOR01,$04b
+ dc.w $a607,$fffe
+ dc.w COLOR01,$16c
+ dc.w $a707,$fffe
+ dc.w COLOR01,$28e
+ dc.w $a807,$fffe
+ dc.w COLOR01,$4ae
+ dc.w $a907,$fffe
+ dc.w COLOR01,$6ce
+ dc.w $aa07,$fffe
+ dc.w COLOR01,$8dd
+ dc.w $ab07,$fffe
+ dc.w COLOR01,$aec
+ dc.w $ac07,$fffe
+ dc.w COLOR01,$cea
+ dc.w $ad07,$fffe
+ dc.w COLOR01,$dd8
+ dc.w $ae07,$fffe
+ dc.w COLOR01,$ec6
+ dc.w $af07,$fffe
+ dc.w COLOR01,$eb4
+ dc.w $b007,$fffe
+ dc.w COLOR01,$e92
+ dc.w $b107,$fffe
+ dc.w COLOR01,$d71
+ dc.w $b207,$fffe
+ dc.w COLOR01,$b50
+ dc.w $b307,$fffe
+ dc.w COLOR01,$930
+ dc.w $b407,$fffe
+ dc.w COLOR01,$711
+ dc.w $b507,$fffe
+ dc.w COLOR01,$502
+ dc.w $b607,$fffe
+ dc.w COLOR01,$303
+ dc.w $b707,$fffe
+ dc.w COLOR01,$205
+ dc.w $b807,$fffe
+ dc.w COLOR01,$117
+ dc.w $b907,$fffe
+ dc.w COLOR01,$039
+ dc.w $ba07,$fffe
+ dc.w COLOR01,$04b
+ dc.w $bb07,$fffe
+ dc.w COLOR01,$16d
+ dc.w $bc07,$fffe
+ dc.w COLOR01,$29e
+ dc.w $bd07,$fffe
+ dc.w COLOR01,$4ae
+ dc.w $be07,$fffe
+ dc.w COLOR01,$6ce
+ dc.w $bf07,$fffe
+ dc.w COLOR01,$8dd
+ dc.w $c007,$fffe
+ dc.w COLOR01,$aec
+ dc.w $c107,$fffe
+ dc.w COLOR01,$cea
+ dc.w $c207,$fffe
+ dc.w COLOR01,$dd8
+ dc.w $c307,$fffe
+ dc.w COLOR01,$ec6
+ dc.w $c407,$fffe
+ dc.w COLOR01,$eb4
+ dc.w $c507,$fffe
+ dc.w COLOR01,$e92
+ dc.w $c607,$fffe
+ dc.w COLOR01,$d61
+ dc.w $c707,$fffe
+ dc.w COLOR01,$b40
+ dc.w $c807,$fffe
+ dc.w COLOR01,$930
+ dc.w $c907,$fffe
+ dc.w COLOR01,$711
+ dc.w $ca07,$fffe
+ dc.w COLOR01,$502
+ dc.w $cb07,$fffe
+ dc.w COLOR01,$303
+ dc.w $cc07,$fffe
+ dc.w COLOR01,$205
+ dc.w $cd07,$fffe
+ dc.w COLOR01,$117
+ dc.w $ce07,$fffe
+ dc.w COLOR01,$039
+ dc.w $cf07,$fffe
+ dc.w COLOR01,$04b
+ dc.w $d007,$fffe
+ dc.w COLOR01,$17d
+ dc.w $d107,$fffe
+ dc.w COLOR01,$29e
+ dc.w $d207,$fffe
+ dc.w COLOR01,$4be
+ dc.w $d307,$fffe
+ dc.w COLOR01,$6ce
+ dc.w $d407,$fffe
+ dc.w COLOR01,$8dd
+ dc.w $d507,$fffe
+ dc.w COLOR01,$aec
+ dc.w $d607,$fffe
+ dc.w COLOR01,$cea
+ dc.w $d707,$fffe
+ dc.w COLOR01,$dd8
+ dc.w $d807,$fffe
+ dc.w COLOR01,$ec6
+ dc.w $d907,$fffe
+ dc.w COLOR01,$ea4
+ dc.w $da07,$fffe
+ dc.w COLOR01,$e82
+ dc.w $db07,$fffe
+ dc.w COLOR01,$d61
+ dc.w $dc07,$fffe
+ dc.w COLOR01,$b40
+ dc.w $dd07,$fffe
+ dc.w COLOR01,$930
+ dc.w $de07,$fffe
+ dc.w COLOR01,$711
+ dc.w $df07,$fffe
+ dc.w COLOR01,$502
+ dc.w $e007,$fffe
+ dc.w COLOR01,$303
+ dc.w $e107,$fffe
+ dc.w COLOR01,$205
+ dc.w $e207,$fffe
+ dc.w COLOR01,$017
+ dc.w $e307,$fffe
+ dc.w COLOR01,$039
+ dc.w $e407,$fffe
+ dc.w COLOR01,$05b
+ dc.w $e507,$fffe
+ dc.w COLOR01,$17d
+ dc.w $e607,$fffe
+ dc.w COLOR01,$29e
+ dc.w $e707,$fffe
+ dc.w COLOR01,$4be
+ dc.w $e807,$fffe
+ dc.w COLOR01,$6ce
+ dc.w $e907,$fffe
+ dc.w COLOR01,$8dd
+ dc.w $ea07,$fffe
+ dc.w COLOR01,$aeb
+ dc.w $eb07,$fffe
+ dc.w COLOR01,$cea
+ dc.w $ec07,$fffe
+ dc.w COLOR01,$dd8
+ dc.w $ed07,$fffe
+ dc.w COLOR01,$ec6
+ dc.w $ee07,$fffe
+ dc.w COLOR01,$ea4
+ dc.w $ef07,$fffe
+ dc.w COLOR01,$d82
+ dc.w $f007,$fffe
+ dc.w COLOR01,$c61
+ dc.w $f107,$fffe
+ dc.w COLOR01,$b40
+ dc.w $f207,$fffe
+ dc.w COLOR01,$920
+ dc.w $f307,$fffe
+ dc.w COLOR01,$711
+ dc.w $f407,$fffe
+ dc.w COLOR01,$502
+ dc.w $f507,$fffe
+ dc.w COLOR01,$303
+ dc.w $f607,$fffe
+ dc.w COLOR01,$105
+ dc.w $f707,$fffe
+ dc.w COLOR01,$017
+ dc.w $f807,$fffe
+ dc.w COLOR01,$03a
+ dc.w $f907,$fffe
+ dc.w COLOR01,$05b
+ dc.w $fa07,$fffe
+ dc.w COLOR01,$17d
+ dc.w $fb07,$fffe
+ dc.w COLOR01,$29e
+ dc.w $fc07,$fffe
+ dc.w COLOR01,$4be
+ dc.w $fd07,$fffe
+ dc.w COLOR01,$6ce
+ dc.w $fe07,$fffe
+ dc.w COLOR01,$8dd
+ dc.w $ff07,$fffe
+ dc.w COLOR01,$aeb
+.verticalPositionWrapped:
+ dc.w $ffdf,$fffe
+ dc.w $7,$fffe
+ dc.w COLOR01,$cea
+ dc.w $107,$fffe
+ dc.w COLOR01,$dd8
+ dc.w $207,$fffe
+ dc.w COLOR01,$ec5
+ dc.w $307,$fffe
+ dc.w COLOR01,$ea3
+ dc.w $407,$fffe
+ dc.w COLOR01,$d82
+ dc.w $507,$fffe
+ dc.w COLOR01,$c61
+ dc.w $607,$fffe
+ dc.w COLOR01,$b40
+ dc.w $707,$fffe
+ dc.w COLOR01,$920
+ dc.w $807,$fffe
+ dc.w COLOR01,$711
+ dc.w $907,$fffe
+ dc.w COLOR01,$502
+ dc.w $a07,$fffe
+ dc.w COLOR01,$304
+ dc.w $b07,$fffe
+ dc.w COLOR01,$106
+ dc.w $c07,$fffe
+ dc.w COLOR01,$018
+ dc.w $d07,$fffe
+ dc.w COLOR01,$03a
+ dc.w $e07,$fffe
+ dc.w COLOR01,$05b
+ dc.w $f07,$fffe
+ dc.w COLOR01,$17d
+ dc.w $1007,$fffe
+ dc.w COLOR01,$29e
+ dc.w $1107,$fffe
+ dc.w COLOR01,$4be
+ dc.w $1207,$fffe
+ dc.w COLOR01,$6ce
+ dc.w $1307,$fffe
+ dc.w COLOR01,$8dd
+ dc.w $1407,$fffe
+ dc.w COLOR01,$aeb
+ dc.w $1507,$fffe
+ dc.w COLOR01,$ce9
+ dc.w $1607,$fffe
+ dc.w COLOR01,$dd7
+ dc.w $1707,$fffe
+ dc.w COLOR01,$ec5
+ dc.w $1807,$fffe
+ dc.w COLOR01,$ea3
+ dc.w $1907,$fffe
+ dc.w COLOR01,$d82
+ dc.w $1a07,$fffe
+ dc.w COLOR01,$c61
+ dc.w $1b07,$fffe
+ dc.w COLOR01,$b40
+ dc.w $1c07,$fffe
+ dc.w COLOR01,$920
+ dc.w $1d07,$fffe
+ dc.w COLOR01,$711
+ dc.w $1e07,$fffe
+ dc.w COLOR01,$502
+ dc.w $1f07,$fffe
+ dc.w COLOR01,$304
+ dc.w $2007,$fffe
+ dc.w COLOR01,$106
+ dc.w $2107,$fffe
+ dc.w COLOR01,$028
+ dc.w $2207,$fffe
+ dc.w COLOR01,$03a
+ dc.w $2307,$fffe
+ dc.w COLOR01,$05c
+ dc.w $2407,$fffe
+ dc.w COLOR01,$17d
+ dc.w $2507,$fffe
+ dc.w COLOR01,$39e
+ dc.w $2607,$fffe
+ dc.w COLOR01,$4be
+ dc.w $2707,$fffe
+ dc.w COLOR01,$6ce
+ dc.w $2807,$fffe
+ dc.w COLOR01,$8ed
+ dc.w $2907,$fffe
+ dc.w COLOR01,$aeb
+ dc.w $2a07,$fffe
+ dc.w COLOR01,$ce9
+ dc.w $2b07,$fffe
+ dc.w COLOR01,$dd7
+ dc.w $2c07,$fffe
+ dc.w COLOR01,$000
diff --git a/028.game2/cpu.s b/028.game2/cpu.s
new file mode 100644
index 0000000..c4eef06
--- /dev/null
+++ b/028.game2/cpu.s
@@ -0,0 +1,28 @@
+ include "includes.i"
+
+ xdef CpuFillColor
+
+CpuFillColor:
+ ;; d0 - color index
+ ;; a0 - bitplane pointer
+ movem.l d1-d4/a0,-(sp)
+ move.w #(SCREEN_HEIGHT)-1,d2
+.fillLine
+ move.b #0,d1 ; bitplane #
+.fillBitplane:
+ move.w #(SCREEN_WIDTH_BYTES/4)-1,d3 ; long word moves, so / 4
+ btst d1,d0 ; is the color's bit set in this plane?
+ beq .zero
+ move.l #$FFFFFFFF,d4 ; yes ? all ones
+ bra .loop
+.zero
+ move.l #0,d4 ; no ? all zeros
+.loop:
+ move.l d4,(a0)+ ; write the data to the plane's line
+ dbra d3,.loop
+ add.b #1,d1
+ cmp.b #SCREEN_BIT_DEPTH,d1 ; all planes for a single line done ?
+ bne .fillBitplane ; no ? do the next plane
+ dbra d2,.fillLine ; yes ? do the next line
+ movem.l (sp)+,d1-d4/a0
+ rts
\ No newline at end of file
diff --git a/028.game2/foreground.tmx b/028.game2/foreground.tmx
new file mode 100644
index 0000000..0a722d1
--- /dev/null
+++ b/028.game2/foreground.tmx
@@ -0,0 +1,11 @@
+
+
diff --git a/028.game2/game1.s b/028.game2/game1.s
new file mode 100644
index 0000000..1b68340
--- /dev/null
+++ b/028.game2/game1.s
@@ -0,0 +1,332 @@
+ include "includes.i"
+
+ xdef copperList
+ xdef copperListBpl1Ptr
+ xdef copperListBpl2Ptr
+ xdef backgroundOnscreen
+ xdef backgroundOffscreen
+ xdef foregroundOnscreen
+ xdef foregroundOffscreen
+ xdef foregroundScrollX
+ xdef backgroundScrollX
+
+byteMap:
+ dc.l Entry
+ dc.l endCode-byteMap
+
+Entry:
+ lea userstack,a7
+ lea CUSTOM,a6
+
+ move #$7ff,DMACON(a6) ; disable all dma
+ move #$7fff,INTENA(a6) ; disable all interrupts
+
+ jsr InstallPalette
+ move.w #$09e,COLOR00(a6)
+ move.w #$09e,COLOR08(a6)
+
+ lea Level3InterruptHandler,a3
+ move.l a3,LVL3_INT_VECTOR
+
+ ;; d0 - fg bitplane pointer offset
+ ;; d1 - bg bitplane pointer offset
+ move.l #0,d0
+ move.l #1,d1
+ jsr SwitchBuffers
+
+ move.w #(INTF_SETCLR|INTF_VERTB|INTF_INTEN),INTENA(a6)
+ move.w #(DMAF_BLITTER|DMAF_SETCLR!DMAF_MASTER),DMACON(a6)
+
+ jsr Init ; enable the playfield
+
+
+Reset:
+ move.l #0,foregroundScrollX ; x pos (d1)
+ move.l #0,fg_shift ; shift counter (d2)
+ move.l #0,fg_tileIndex ; tile index (d3)
+ move.l #0,backgroundScrollX
+ move.l #0,bg_shift ; shift counter (d2)
+ move.l #0,bg_tileIndex ; tile index (d3)
+ move.l #BACKGROUND_UPDATE_COUNT,d6 (Frame count)
+ jsr BlueFill
+ move.l #0,frameCount
+
+MainLoop:
+ move.l frameCount,d6
+
+
+ bsr RenderNextForegroundFrame
+ bsr RenderNextBackgroundFrame
+
+ jsr WaitVerticalBlank
+ bsr.s HoriScrollPlayfield
+ jsr SwitchBuffers ; takes bitplane pointer offset in d0
+
+ andi.b #BACKGROUND_UPDATE_COUNT,d6
+ bne .skipBackgroundUpdates
+ ;; ---- Background updates ----------------------------------------
+.backgroundUpdates:
+ add.l #1,backgroundScrollX
+ add.l #2,bg_tileIndex ; increment tile index by a word
+ bsr UpdateBackgroundShiftCounter
+.skipBackgroundUpdates:
+
+ btst #FOREGROUND_DELAY_BIT,d6
+ beq .skipForegroundUpdates
+ ;; ---- Foreground updates ----------------------------------------
+.foregroundUpdates:
+ add.l #1,foregroundScrollX
+ cmp.l #8,fg_shift
+ bge .skip
+ add.l #2,fg_tileIndex ; increment foreground tile index
+.skip:
+ bsr UpdateShiftCounter
+.skipForegroundUpdates:
+
+ add.l #1,frameCount
+
+ bra MainLoop
+
+HoriScrollPlayfield:
+ ;; d0 - fg x position in pixels
+ ;; d1 - bg x position in pixels
+ ;; movem.l d0-d6,-(sp)
+
+ move.l backgroundScrollX,d0
+
+ move.w d0,d2
+ lsr.w #3,d0 ; bytes to scroll
+ and.w #$F,d2 ; pixels = 0xf - (hpos - (hpos_bytes*8))
+ move.w #$F,d0
+ sub.w d2,d0 ; bits to delay
+ move.w d0,d5 ; d5 == bg bits to delay
+
+ move.l foregroundScrollX,d0
+ move.w d0,d2
+ lsr.w #3,d0 ; bytes to scroll
+ and.w #$F,d2 ; pixels = 0xf - (hpos - (hpos_bytes*8))
+ move.w #$F,d0
+ sub.w d2,d0 ; bits to delay
+
+ lsl.w #4,d5
+ or.w d5,d0
+
+ move.w d0,BPLCON1(a6)
+
+ ;; movem.l (sp)+,d0-d6
+ rts
+
+
+
+RenderNextBackgroundFrame:
+ btst #FOREGROUND_DELAY_BIT,d6
+ beq .s1
+ lea backgroundMap,a2
+ add.l bg_tileIndex,a2
+ bsr RenderBackgroundTile
+.s1:
+ rts
+
+RenderNextForegroundFrame:
+ lea map,a2
+ add.l fg_tileIndex,a2
+ cmp.w #$FFFF,20(a2)
+ bne .skip
+ bra Reset
+.skip:
+ bsr RenderForegroundTile
+ bsr ClearForegroundTile
+ rts
+
+
+RenderForegroundTile:
+ ;; a2 - address of tileIndex
+ move.l foregroundScrollX,d0
+ lsr.w #3,d0 ; bytes to scroll
+ move.l foregroundOffscreen,a0
+ add.l d0,a0
+ lea tilemap,a1
+ add.l #BITPLANE_WIDTH_BYTES-8,a0 ; dest
+ add.w (a2),a1 ; source tile
+ move.l fg_shift,d2
+ cmp.l #8,d2
+ bge .skip
+ jsr BlitTile
+.skip:
+ rts
+
+ClearForegroundTile
+ lea tilemap,a1
+ add.w #11520,a1 ; source tile
+ move.l fg_shift,d2
+ sub.l #32,a0
+ jsr BlitTile
+ rts
+
+
+RenderBackgroundTile:
+ ;; a2 - map
+ move.l backgroundScrollX,d0
+ lsr.w #3,d0 ; bytes to scroll
+ move.l backgroundOffscreen,a0
+ add.l d0,a0
+ lea backgroundTilemap,a1
+ add.l #BITPLANE_WIDTH_BYTES-2,a0 ; dest
+ add.w (a2),a1 ; source tile
+ move.l bg_shift,d2
+ jsr BlitTile
+ rts
+
+UpdateShiftCounter:
+ cmp.l #15,fg_shift
+ bne .s1
+ move.l #0,fg_shift
+ bra .s2
+.s1:
+ add.l #1,fg_shift
+.s2:
+ rts
+
+UpdateBackgroundShiftCounter:
+ cmp.l #15,bg_shift
+ bne .s1
+ move.l #0,bg_shift
+ bra .s2
+.s1:
+ add.l #1,bg_shift
+.s2:
+ rts
+
+
+Level3InterruptHandler:
+ movem.l d0-a6,-(sp)
+ lea CUSTOM,a6
+.checkVerticalBlank:
+ move.w INTREQR(a6),d0
+ and.w #INTF_VERTB,d0
+ beq.s .checkCopper
+
+.verticalBlank:
+ move.w #INTF_VERTB,INTREQ(a6) ; clear interrupt bit
+.checkCopper:
+ move.w INTREQR(a6),d0
+ and.w #INTF_COPER,d0
+ beq.s .interruptComplete
+.copperInterrupt:
+ move.w #INTF_COPER,INTREQ(a6) ; clear interrupt bit
+
+.interruptComplete:
+ movem.l (sp)+,d0-a6
+ rte
+
+
+copperList:
+copperListBpl1Ptr:
+ ;; this is where bitplanes are assigned to playfields
+ ;; http://amigadev.elowar.com/read/ADCD_2.1/Hardware_Manual_guide/node0079.html
+ ;; 3 bitplanes per playfield, playfield1 gets bitplanes 1,3,5
+ dc.w BPL1PTL,0
+ dc.w BPL1PTH,0
+ dc.w BPL3PTL,0
+ dc.w BPL3PTH,0
+ dc.w BPL5PTL,0
+ dc.w BPL5PTH,0
+copperListBpl2Ptr:
+ ;; 3 bitplanes per playfield, playfield2 gets bitplanes 2,4,6
+ dc.w BPL2PTL,0
+ dc.w BPL2PTH,0
+ dc.w BPL4PTL,0
+ dc.w BPL4PTH,0
+ dc.w BPL6PTL,0
+ dc.w BPL6PTH,0
+ dc.l $fffffffe
+
+
+InstallPalette:
+ include "out/tilemap-palette.s"
+ rts
+
+foregroundOnscreen:
+ dc.l foregroundBitplanes1
+foregroundOffscreen:
+ dc.l foregroundBitplanes2
+backgroundOnscreen:
+ dc.l backgroundBitplanes1
+backgroundOffscreen:
+ dc.l backgroundBitplanes2
+tilemap:
+ incbin "out/foreground.bin"
+backgroundTilemap:
+ incbin "out/background.bin"
+map:
+ include "out/foreground-map.s"
+ dc.w $FFFF
+backgroundMap:
+ include "out/background-map.s"
+fg_shift:
+ dc.l 0
+foregroundScrollX:
+ dc.l 0
+fg_tileIndex:
+ dc.l 0
+bg_shift:
+ dc.l 0
+backgroundScrollX:
+ dc.l 0
+bg_tileIndex:
+ dc.l 0
+frameCount:
+ dc.l 0
+
+ section .bss
+foregroundBitplanes1:
+ ds.b IMAGESIZE
+ ds.b BITPLANE_WIDTH_BYTES*20
+foregroundBitplanes2:
+ ds.b IMAGESIZE
+ ds.b BITPLANE_WIDTH_BYTES*20
+
+backgroundBitplanes1:
+ ds.b IMAGESIZE
+ ds.b BITPLANE_WIDTH_BYTES*20
+backgroundBitplanes2:
+ ds.b IMAGESIZE
+ ds.b BITPLANE_WIDTH_BYTES*20
+
+
+startUserstack:
+ ds.b $1000 ; size of stack
+userstack:
+
+
+
+ end
+
+0: UpdateFG
+ UpdateBG
+ RenderFG
+ RenderBG
+ SwapBufferFG
+ SwapBufferBG
+
+1: RenderFG
+ SwapBufferFG
+
+2: UpdateFG
+ RenderFG
+ RenderBG
+ SwapBufferFG
+ SwapBufferBG
+
+2: RenderFG
+ SwapBufferFG
+
+
+000
+001
+010
+011
+100
+101
+110
+111
diff --git a/028.game2/image.s b/028.game2/image.s
new file mode 100644
index 0000000..f48ce61
--- /dev/null
+++ b/028.game2/image.s
@@ -0,0 +1,52 @@
+ include "includes.i"
+
+ xdef SwitchBuffers
+
+SwitchBuffers:
+ ;; offscreen - bitplane address
+ ;; movem.l d0/a0-a1,-(sp)
+
+ move.l foregroundScrollX,d0
+ lsr.l #3,d0 ; bytes to scroll
+ move.l foregroundOffscreen,a0
+ move.l foregroundOnscreen,foregroundOffscreen
+ move.l a0,foregroundOnscreen
+ move.l a0,a1
+ lea copperListBpl1Ptr,a0
+ jsr PokeBitplanePointers
+
+ btst #FOREGROUND_DELAY_BIT,d6 ; only swap the background buffer every second frame
+ beq .skipBackgroundSwap
+ move.l backgroundScrollX,d0
+ lsr.l #3,d0 ; bytes to scroll
+ move.l backgroundOffscreen,a0
+ move.l backgroundOnscreen,backgroundOffscreen
+ move.l a0,backgroundOnscreen
+ move.l a0,a1
+ lea copperListBpl2Ptr,a0
+ jsr PokeBitplanePointers
+.skipBackgroundSwap:
+ ;; movem.l (sp)+,d0/a0-a1
+ rts
+
+PokeBitplanePointers:
+ ; d0 = frame offset in bytes
+ ; a0 = BPLP copper list address
+ ; a1 = bitplanes pointer
+ ;; movem.l d0-a6,-(sp)
+ add.l d0,a1 ; bitplane offset
+ moveq #SCREEN_BIT_DEPTH-1,d0
+.bitplaneloop:
+ move.l a1,d1
+ move.w d1,2(a0)
+ swap d1
+ move.w d1,6(a0)
+ lea BITPLANE_WIDTH_BYTES(a1),a1
+ addq #8,a0
+ dbra d0,.bitplaneloop
+ ;; movem.l (sp)+,d0-a6
+ rts
+
+
+
+
diff --git a/028.game2/includes.i b/028.game2/includes.i
new file mode 100644
index 0000000..34a2b64
--- /dev/null
+++ b/028.game2/includes.i
@@ -0,0 +1,9 @@
+ include "../include/registers.i"
+ include "../include/vector.i"
+ include "../include/beambits.i"
+ include "../include/bplconbits.i"
+ include "hardware/dmabits.i"
+ include "hardware/intbits.i"
+ include "hardware/blit.i"
+ include "constants.i"
+ include "macros.i"
\ No newline at end of file
diff --git a/028.game2/init.s b/028.game2/init.s
new file mode 100644
index 0000000..5b146ec
--- /dev/null
+++ b/028.game2/init.s
@@ -0,0 +1,34 @@
+ include "includes.i"
+
+ xdef Init
+
+ ;; custom chip base globally in a6
+Init:
+ movem.l d0-a6,-(sp)
+ ;; move #$7ff,DMACON(a6) ; disable all dma
+ ;; move #$7fff,INTENA(a6) ; disable all interrupts
+
+ ;; lea Level3InterruptHandler,a3
+ ;; move.l a3,LVL3_INT_VECTOR
+
+ ;; set up playfield
+ move.w #(RASTER_Y_START<<8)|RASTER_X_START,DIWSTRT(a6)
+ move.w #((RASTER_Y_STOP-256)<<8)|(RASTER_X_STOP-256),DIWSTOP(a6)
+
+ move.w #(RASTER_X_START/2-SCREEN_RES)-8,DDFSTRT(a6) ; -8 for extra scrolling word
+ move.w #(RASTER_X_START/2-SCREEN_RES)+(8*((SCREEN_WIDTH/16)-1)),DDFSTOP(a6)
+
+ ;; enabled 2x the bitplanes as 2x playfields
+ move.w #(SCREEN_BIT_DEPTH*2<<12)|COLOR_ON|DBLPF,BPLCON0(a6)
+ move.w #BITPLANE_WIDTH_BYTES*SCREEN_BIT_DEPTH-SCREEN_WIDTH_BYTES-2,BPL1MOD(a6) ; -2 for extra scrolling word
+ move.w #BITPLANE_WIDTH_BYTES*SCREEN_BIT_DEPTH-SCREEN_WIDTH_BYTES-2,BPL2MOD(a6)
+
+ ;; install copper list, then enable dma and selected interrupts
+ lea copperList,a0
+ move.l a0,COP1LC(a6)
+ move.w COPJMP1(a6),d0
+ move.w #(DMAF_BLITTER|DMAF_SETCLR!DMAF_COPPER!DMAF_RASTER!DMAF_MASTER),DMACON(a6)
+ ;; move.w #PF2PRI,BPLCON2(a6)
+ ;; move.w #(INTF_SETCLR|INTF_VERTB|INTF_INTEN),INTENA(a6)
+ movem.l (sp)+,d0-a6
+ rts
\ No newline at end of file
diff --git a/028.game2/link.script.x b/028.game2/link.script.x
new file mode 100644
index 0000000..4933239
--- /dev/null
+++ b/028.game2/link.script.x
@@ -0,0 +1,28 @@
+MEMORY
+{
+ disk: org = 0x4000, len = 901120-0x4000
+ ram: org = 0x00000, len = 0x80000
+}
+
+SECTIONS
+{
+ load : {
+ startCode = .;
+ *(.text)
+ *(.data)
+ *(CODE)
+ *(DATA)
+ endCode = .;
+ } > disk
+
+ noload ALIGN(512) : {
+ startData = .;
+ *(.noload)
+ endData = .;
+ } > disk
+
+ bss (NOLOAD) : {
+ . = endCode;
+ *(.bss)
+ } > ram;
+}
\ No newline at end of file
diff --git a/028.game2/macros.i b/028.game2/macros.i
new file mode 100644
index 0000000..d19a071
--- /dev/null
+++ b/028.game2/macros.i
@@ -0,0 +1,6 @@
+WaitBlitter: macro
+ tst DMACONR(a6) ;for compatibility
+.\@:
+ btst #6,DMACONR(a6)
+ bne.s .\@
+ endm
\ No newline at end of file
diff --git a/028.game2/utils.s b/028.game2/utils.s
new file mode 100644
index 0000000..0d36fb8
--- /dev/null
+++ b/028.game2/utils.s
@@ -0,0 +1,47 @@
+ include "includes.i"
+
+ xdef WaitVerticalBlank
+ xdef WaitRaster
+ xdef Depack
+
+
+WaitVerticalBlank:
+ movem.l d0,-(sp)
+.loop: move.l $dff004,d0
+ and.l #$1ff00,d0
+ cmp.l #303<<8,d0 ; wait for the scan line
+ bne.b .loop
+.loop2 move.l $dff004,d0
+ and.l #$1ff00,d0
+ cmp.l #303<<8,d0 ; wait for the scan line to pass (A4000 is fast!)
+ beq.b .loop2
+ movem.l (sp)+,d0
+ rts
+
+
+WaitRaster: ;wait for rasterline d0.w. Modifies d0-d2/a0.
+ movem.l d0-a6,-(sp)
+ move.l #$1ff00,d2
+ lsl.l #8,d0
+ and.l d2,d0
+ lea $dff004,a0
+.wr: move.l (a0),d1
+ and.l d2,d1
+ cmp.l d1,d0
+ bne.s .wr
+ movem.l (sp)+,d0-a6
+ rts
+
+
+Depack:
+ ;a0 = input buffer to be decompressed. Must be 16-bit aligned!
+ ;a1 = output buffer. Points to the end of the data at exit
+ movem.l d0-a6,-(sp)
+ bsr doynaxdepack ; decompress data
+ movem.l (sp)+,d0-a6
+ rts
+
+ ;; this is one FAST decompression routine!
+ include "../tools/external/doynamite68k/depacker_doynax.asm"
+
+