Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- ; Technical demo: sliding overlapping rectangles
- ; (C)2021 Miguel A. Rodriguez-Jodar ( mcleod_ideafix )
- ; ZX Projects.
- ;
- ; This program is free software: you can redistribute it and/or modify
- ; it under the terms of the GNU General Public License as published by
- ; the Free Software Foundation, either version 3 of the License, or
- ; (at your option) any later version.
- ;
- ; This program is distributed in the hope that it will be useful,
- ; but WITHOUT ANY WARRANTY; without even the implied warranty of
- ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- ; GNU General Public License for more details.
- ;
- ; You should have received a copy of the GNU General Public License
- ; along with this program. If not, see <https://www.gnu.org/licenses/>.
- ; Assemble using PASMO: pasmo --tapbas sliding_rectangles.asm sliding_rectangles.tap
- X equ 0 ; offset to X and Y coordinate
- Y equ 1 ; of top left pixel of rectangle
- WIDTH equ 2 ; offset to width and height
- HEIGHT equ 3 ;
- SPEEDPAT equ 4 ; offset to binary pattern indicating which frame the rectangle is animated
- SPEEDMULT equ 5 ; offset to value indicating how many pixels the rectangle is moved
- LSTRU equ 6 ; length of all fields above.
- PIXEL_ADDRESS equ 22B1h ; C=x, B=y, A=y. Returns HL=address, A=x mod 8
- org 49152
- Main proc
- xor a ;
- out (254),a ;
- ld hl,16384 ;
- ld de,16385 ; Clear screen to bright B/W
- ld bc,6143 ;
- ld (hl),a ;
- ldir ;
- inc hl ;
- inc de ;
- ld (hl),71 ;
- ld bc,767 ;
- ldir ;
- ld (23560),a ; Clear 1-byte keyboard buffer
- ld ix,RectTable ; RectTable contains a list of rectangles
- InitialParseTable ld a,(ix+HEIGHT)
- inc a
- jr z,EndInitialDrawing ; A rectangle with height=255 marks the end of the list
- call DrawInitialRectangle ; Draws rectangle
- ld de,LSTRU
- add ix,de ; next rectangle
- jr InitialParseTable
- EndInitialDrawing
- LoopMoveAll ld a,(23560) ; Read last pressed key
- cp 32 ; if SPACE is presssed, then
- ret z ; return to BASIC
- ld ix,RectTable ; Now we parse RectTable to move the rectangles
- ParseTable ld a,(ix+HEIGHT)
- inc a ;
- jr z,LoopMoveAll ; if we reach the end of the table, start it all over again
- call MoveOneRectangle ; move one rectangle
- ld de,LSTRU
- add ix,de ; next rectangle
- jr ParseTable
- endp
- DrawInitialRectangle proc
- ld d,(ix+HEIGHT) ;
- ld c,(ix+X) ; Retrieve rectangle parameters
- ld b,(ix+Y) ; from the current entry of RectTable
- ld e,(ix+WIDTH) ;
- DrawOneLine call DrawLine ;
- inc b ; simple loop to draw a rectangle by drawing all the horizontal
- dec d ; lines that comprises it.
- jr nz,DrawOneLine ;
- ret
- endp
- MoveOneRectangle proc
- ld a,(ix+SPEEDPAT) ; load SPEEDPAT for current rect
- rrc (ix+SPEEDPAT) ; and rotate it for the next frame
- bit 0,a ; time to animate this rect?
- ret z
- ld b,(ix+SPEEDMULT) ; load how many pixels we have to move this rectangle
- Move1PixelDown push bc
- ld d,(ix+HEIGHT)
- ld c,(ix+X)
- ld b,(ix+Y)
- ld e,(ix+WIDTH)
- call DrawLine ; Draws the top line of the rectangle (actually erasing it)
- ld a,b
- add a,d
- call AdjustBottomScreen
- ld b,a ; Move to the line below the last line of the rectangle and draws it
- call DrawLine
- ld a,(ix+Y)
- inc a ; This rectangle has moved 1 pixel.
- call AdjustBottomScreen
- ld (ix+Y),a
- pop bc
- djnz Move1PixelDown ; Go back to move it again, if needed
- ret
- endp
- AdjustBottomScreen proc
- jr nc,NoAdjustOverflow ;
- sub 192 ; Computes A mod 192
- ret ; even if A overflowed
- NoAdjustOverflow cp 192 ; after an addition (i.e.
- ret c ; 180 + 100 = 280, which
- sub 192 ; doesn't fit in 8 bits)
- ret ; This is to roll back to the top of the screen
- endp
- DrawLine proc
- push bc
- push de
- ld a,b ; The next routine needs this
- call PIXEL_ADDRESS ; Calculate screen address (ROM routine)
- ld c,a ;
- or a ; Pixel 0 of this byte?
- ld a,0FFh ; Assume we fill the entire 8-pixel row
- jr z,DontShiftRight ; So there's no need to shift the 8-pixel row
- ld b,a ;
- ShiftRight srl a ; Not pixel 0, so we shift to the right until pixel B
- djnz ShiftRight ;
- DontShiftRight xor (hl) ; OVER 1 with screen
- ld (hl),a ; and store
- ld a,8 ;
- sub c ; Compute how many pixels we painted in the code before
- ld c,a ; and update E (line width) so there are less pixels to paint
- ld a,e ;
- sub c ;
- Paint8Pixels cp 9 ; If there are less than 9 pixels still to paint...
- ld e,a
- inc hl
- jr c,PaintRightSide ; then go calculate how many of them and paint them
- ld a,(hl) ; If there are more than 8 pixels, then a complete 8-pixel row can be painted
- cpl ; just by OVERing 1 the current 8-pixel row
- ld (hl),a ; and storing it again
- ld a,e ;
- sub 8 ; 8 more pixels painted
- jr Paint8Pixels ; go see if there are still more than 8 pixels
- PaintRightSide ld a,128 ; We generate a value in A with just one high bit at the left (bit 7)
- ShiftRightSide dec e ; If this is was the only pixel to paint
- jr z,FinishShift ; then go paint it
- sra a ; If not, first replicate the 1-bit at bit 7 as much times as pixels are left to paint
- jr ShiftRightSide
- FinishShift xor (hl) ; combine it with the current screen contents
- ld (hl),a ; and store it
- pop de
- pop bc
- ret
- endp
- ; Format: each db line is a rectangle.
- ; x-coordinate (0-246), y coordinate (0-191), width (must be > 8), height (1-191), animation pattern, animation mutiplier
- ; Rectangle must initially fit on screen
- ; Animation pattern: each frame, bit 0 of this value is checked. If 0, the rectangle is not moved down. If 1, it is moved down.
- ; Whether it has been moved or not, this value rotates one bit to the right
- ; Animation multiplier: if the animation pattern bit is 1, this value indicates how many pixels the rectangle has to be moved.
- ;
- ; Animation pattern can be crafted to get slower than 1 pixel/frame moving
- ; For fast moving rectangles, use a higher animation multiplier
- RectTable db 18,0,80,100, 01010101b,1
- db 32,70,30,80, 11111111b,3
- db 128,88,100,46, 11111111b,5
- db 190,38,30,150, 11111111b,1
- db 150,40,20,90, 10101010b,2
- db 85,120,80,40, 11111111b,3
- db 130,10,50,130, 00010001b,1
- db 20,88,24,64, 11111111b,4
- db 140,2,30,130, 11111111b,2
- db 255,255,255,255,255 ; end of table
- end Main
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement