From d577a4ae717b1e309eeebe895faf56ad60739435 Mon Sep 17 00:00:00 2001 From: alpine9000 Date: Tue, 5 Apr 2016 15:48:02 +1000 Subject: [PATCH] Start of tile_hscroll --- 026.tile_hscroll/Makefile | 33 ++ 026.tile_hscroll/README.md | 13 + 026.tile_hscroll/alpine_bootblock.s | 352 +++++++++++++++++++ 026.tile_hscroll/blit.s | 128 +++++++ 026.tile_hscroll/blitchar.s | 87 +++++ 026.tile_hscroll/constants.i | 33 ++ 026.tile_hscroll/copperlist.s | 516 ++++++++++++++++++++++++++++ 026.tile_hscroll/cpu.s | 28 ++ 026.tile_hscroll/image.s | 36 ++ 026.tile_hscroll/includes.i | 9 + 026.tile_hscroll/init.s | 32 ++ 026.tile_hscroll/link.script.x | 28 ++ 026.tile_hscroll/macros.i | 6 + 026.tile_hscroll/palette.pal | 17 + 026.tile_hscroll/screenshot.png | Bin 0 -> 26253 bytes 026.tile_hscroll/scroll.s | 30 ++ 026.tile_hscroll/test.asm | 20 ++ 026.tile_hscroll/test.c | 4 + 026.tile_hscroll/tile_hscroll.s | 123 +++++++ 026.tile_hscroll/utils.s | 47 +++ 20 files changed, 1542 insertions(+) create mode 100644 026.tile_hscroll/Makefile create mode 100644 026.tile_hscroll/README.md create mode 100644 026.tile_hscroll/alpine_bootblock.s create mode 100644 026.tile_hscroll/blit.s create mode 100644 026.tile_hscroll/blitchar.s create mode 100644 026.tile_hscroll/constants.i create mode 100644 026.tile_hscroll/copperlist.s create mode 100644 026.tile_hscroll/cpu.s create mode 100644 026.tile_hscroll/image.s create mode 100644 026.tile_hscroll/includes.i create mode 100644 026.tile_hscroll/init.s create mode 100644 026.tile_hscroll/link.script.x create mode 100644 026.tile_hscroll/macros.i create mode 100644 026.tile_hscroll/palette.pal create mode 100644 026.tile_hscroll/screenshot.png create mode 100644 026.tile_hscroll/scroll.s create mode 100644 026.tile_hscroll/test.asm create mode 100644 026.tile_hscroll/test.c create mode 100644 026.tile_hscroll/tile_hscroll.s create mode 100644 026.tile_hscroll/utils.s diff --git a/026.tile_hscroll/Makefile b/026.tile_hscroll/Makefile new file mode 100644 index 0000000..eec292f --- /dev/null +++ b/026.tile_hscroll/Makefile @@ -0,0 +1,33 @@ +EXAMPLE_NAME=tile_hscroll + +# 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=16 + +BOOTBLOCK_ASM=alpine_bootblock.s +OBJS=out/init.o out/utils.o out/image.o out/blit.o out/scroll.o + +IMAGES=gigi_full.png +IMAGEDATA=$(addprefix out/, $(IMAGES:.png=.bin)) +SIZEDIMAGEDATA=$(addprefix out/, $(IMAGES:.png=.sized.png)) +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=336 --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/blit.o: constants.i macros.i +out/main.o: $(IMAGEDATA) constants.i macros.i Makefile link.script.x palette.pal +out/init.o: constants.i Makefile \ No newline at end of file diff --git a/026.tile_hscroll/README.md b/026.tile_hscroll/README.md new file mode 100644 index 0000000..192077e --- /dev/null +++ b/026.tile_hscroll/README.md @@ -0,0 +1,13 @@ +tile hscroll +============ + +screenshot +---------- + +![Screenshot](screenshot.png?raw=true) + + +try it +------ + * [Download disk image](bin/tile_hscroll.adf?raw=true) + * Run in SAE diff --git a/026.tile_hscroll/alpine_bootblock.s b/026.tile_hscroll/alpine_bootblock.s new file mode 100644 index 0000000..1953463 --- /dev/null +++ b/026.tile_hscroll/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/026.tile_hscroll/blit.s b/026.tile_hscroll/blit.s new file mode 100644 index 0000000..5727d7c --- /dev/null +++ b/026.tile_hscroll/blit.s @@ -0,0 +1,128 @@ + include "includes.i" + + xdef BlitFillColor + xdef BlitScroll + xdef BlitTile + +;; 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 bitplane pointer + ;; d2 - y destination in pixels + + WaitBlitter + + move.w #0,BLTCON1(a6) ; + move.w #BC0F_SRCA|BC0F_DEST|$f0,BLTCON0(a6) + + move.w #SCREEN_WIDTH_BYTES,BLTAMOD(a6) + move.w #SCREEN_WIDTH_BYTES,BLTDMOD(a6) ; + move.l a1,BLTAPTH(a6) ; source + move.l a0,BLTDPTH(a6) ; dest + move.w #$ffff,BLTAFWM(a6) + move.w #$ffff,BLTALWM(a6) + move.w #((SCREEN_HEIGHT/2)*SCREEN_BIT_DEPTH)<<6|(1),BLTSIZE(a6) ;rectangle size, starts blit + + WaitBlitter + + add.l #BITPLANE_WIDTH_BYTES*(SCREEN_HEIGHT/2)*SCREEN_BIT_DEPTH,a0 + add.l #BITPLANE_WIDTH_BYTES*(SCREEN_HEIGHT/2)*SCREEN_BIT_DEPTH,a1 + move.l a1,BLTAPTH(a6) ; source + move.l a0,BLTDPTH(a6) ; dest + move.w #((SCREEN_HEIGHT/2)*SCREEN_BIT_DEPTH)<<6|(1),BLTSIZE(a6) ;rectangle size, starts blit + rts + \ No newline at end of file diff --git a/026.tile_hscroll/blitchar.s b/026.tile_hscroll/blitchar.s new file mode 100644 index 0000000..2e2ac7f --- /dev/null +++ b/026.tile_hscroll/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/026.tile_hscroll/constants.i b/026.tile_hscroll/constants.i new file mode 100644 index 0000000..0c3859a --- /dev/null +++ b/026.tile_hscroll/constants.i @@ -0,0 +1,33 @@ +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 336 +BITPLANE_WIDTH_BYTES equ BITPLANE_WIDTH/8 +BITPLANE_WIDTH_WORDS equ BITPLANE_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/026.tile_hscroll/copperlist.s b/026.tile_hscroll/copperlist.s new file mode 100644 index 0000000..861bad4 --- /dev/null +++ b/026.tile_hscroll/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/026.tile_hscroll/cpu.s b/026.tile_hscroll/cpu.s new file mode 100644 index 0000000..c4eef06 --- /dev/null +++ b/026.tile_hscroll/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/026.tile_hscroll/image.s b/026.tile_hscroll/image.s new file mode 100644 index 0000000..8395dcc --- /dev/null +++ b/026.tile_hscroll/image.s @@ -0,0 +1,36 @@ + include "includes.i" + + xdef SwitchBuffers + +SwitchBuffers: + ;; offscreen - bitplane address + ;; d0 - bitplane pointer offset + movem.l d0/a0-a1,-(sp) + move.l offscreen,a0 + move.l onscreen,offscreen + move.l a0,onscreen + move.l a0,a1 + lea copperListBplPtr,a0 + jsr PokeBitplanePointers + 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/026.tile_hscroll/includes.i b/026.tile_hscroll/includes.i new file mode 100644 index 0000000..34a2b64 --- /dev/null +++ b/026.tile_hscroll/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/026.tile_hscroll/init.s b/026.tile_hscroll/init.s new file mode 100644 index 0000000..7be4860 --- /dev/null +++ b/026.tile_hscroll/init.s @@ -0,0 +1,32 @@ + 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) + + move.w #(SCREEN_BIT_DEPTH<<12)|COLOR_ON,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 #(INTF_SETCLR|INTF_VERTB|INTF_INTEN),INTENA(a6) + movem.l (sp)+,d0-a6 + rts \ No newline at end of file diff --git a/026.tile_hscroll/link.script.x b/026.tile_hscroll/link.script.x new file mode 100644 index 0000000..4933239 --- /dev/null +++ b/026.tile_hscroll/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/026.tile_hscroll/macros.i b/026.tile_hscroll/macros.i new file mode 100644 index 0000000..d19a071 --- /dev/null +++ b/026.tile_hscroll/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/026.tile_hscroll/palette.pal b/026.tile_hscroll/palette.pal new file mode 100644 index 0000000..2412597 --- /dev/null +++ b/026.tile_hscroll/palette.pal @@ -0,0 +1,17 @@ +000 000 000 255 +255 255 255 255 +255 000 000 255 +000 255 000 255 +000 000 255 255 +055 255 055 255 +255 255 000 255 +255 255 000 255 +255 255 000 255 +255 255 000 255 +255 255 000 255 +255 255 000 255 +255 255 000 255 +255 255 000 255 +255 255 000 255 +255 200 000 255 + diff --git a/026.tile_hscroll/screenshot.png b/026.tile_hscroll/screenshot.png new file mode 100644 index 0000000000000000000000000000000000000000..c4ab0fbc1b1d455b86afbeecdd7a856b58cd9afc GIT binary patch literal 26253 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 WY9i