diff --git a/examples/animate.pas b/examples/animate.pas new file mode 100644 index 0000000..2869c46 --- /dev/null +++ b/examples/animate.pas @@ -0,0 +1,136 @@ +program animate; +uses sprites; + +type PictData = record + magic,mode:integer; + palette: array [0..15] of integer; + pixeldata: array [0..31999] of integer; + end; + + Sprite = record + x,y:integer; + oldX,oldY:integer; + xdelta,ydelta:integer; + curFrame:integer; + frameCount:integer; + frameTime:integer; + frameLeft:integer; + changed:boolean; + frame:array [0..3] of SpritePixels; + end; + +var pic:PictData; + filename:string; + infile:file; + ch:char; + stickMan:Sprite; + +procedure WaitVSync; external; + +procedure loadPalette(var pic:PictData); +var i:integer; +begin + for i := 0 to 15 do + setpalette(i, pic.palette[i]); +end; + +procedure showPic(var pic:PictData); +begin + PutScreen(pic.pixeldata); +end; + +procedure loadSpriteFrame(var aSprite:Sprite;spriteIndex:integer; + var sheetFile:file;sheetIndex:integer); +begin + seek(sheetFile, 8 + sheetIndex * 512); + read(sheetFile, aSprite.frame[spriteIndex]); + if aSprite.frameCount <= spriteIndex then + aSprite.frameCount := spriteIndex + 1; + + aSprite.curFrame := 0; + writeln('loaded sprite frame ', spriteIndex, ' from ', sheetIndex); +end; + +procedure animateSprite(var aSprite:Sprite); +var frameIndex:integer; + frameTime,frameLeft:integer; + ydelta:integer; + oldX,oldY:integer; +begin + ydelta := aSprite.ydelta; + frameIndex := aSprite.curFrame; + frameTime := aSprite.frameTime; + frameLeft := aSprite.frameLeft; + oldX := aSprite.x; oldY := aSprite.y; + aSprite.oldX := oldX; aSprite.oldY := oldY; + + frameLeft := frameLeft - 1; + if frameLeft <= 0 then + begin + frameIndex := frameIndex + 1; + frameLeft := aSPrite.frameTime; + aSprite.frameLeft := frameLeft; + aSprite.curFrame := frameIndex; + if frameIndex >= aSprite.frameCount then + aSprite.curFrame := 0; + + aSprite.frameLeft := frameLeft; + + aSprite.x := aSprite.x + aSprite.xdelta; + aSprite.y := aSprite.y + aSprite.ydelta; + + if aSprite.x > 608 then aSprite.x := 0; + end; + aSprite.frameLeft := frameLeft; +end; + +procedure animLoop; +var i:integer; + oldX,oldY:integer; +begin + stickMan.x := 0; + stickMan.y := 310; + stickMan.frameTime := 6; + stickMan.frameLeft := stickMan.frameTime; + stickMan.curFrame := 0; + stickMan.xdelta := 2; + stickMan.ydelta := 0; + + oldX := stickMan.x; + oldY := stickMan.y; + + while not ConAvail do + begin + oldX := stickMan.x; + oldY := stickMan.y; + + PutSprite(oldX, oldY, stickMan.frame[stickMan.curFrame]); + + animateSprite(stickMan); + Delay(10); + WaitVSync; + + UndrawSprite(oldX, oldY, pic.pixeldata); + end; +end; + +begin + filename := 'grey.pict'; + open(infile, filename, ModeReadonly); + read(infile, pic); + close(infile); + + writeln('magic: ', pic.magic, ' mode:', pic.mode); + + loadPalette(pic); + showPic(pic); + + open(infile, 'Walking.sprt', ModeReadOnly); + loadSpriteFrame(stickMan, 0, infile, 0); + loadSpriteFrame(stickMan, 1, infile, 1); + loadSpriteFrame(stickMan, 2, infile, 2); + loadSpriteFrame(stickMan, 3, infile, 3); + close(infile); + + animLoop; +end. diff --git a/examples/grey.pict b/examples/grey.pict new file mode 100644 index 0000000..da05406 Binary files /dev/null and b/examples/grey.pict differ diff --git a/examples/sprites.inc b/examples/sprites.inc index 2b25366..2713c8e 100644 --- a/examples/sprites.inc +++ b/examples/sprites.inc @@ -1,4 +1,4 @@ -type SpritePixels = array[0..31] of integer; +type SpritePixels = array[0..128] of integer; type BackgroundPixels = array[0..31999] of integer; procedure PutSprite(x,y:integer; var sprite: SpritePixels); external; diff --git a/examples/sprites.s b/examples/sprites.s index 42a3d0e..3391339 100644 --- a/examples/sprites.s +++ b/examples/sprites.s @@ -1,4 +1,5 @@ - .EQU SPRITE_HEIGHT 16 + .EQU SPRITE_HEIGHT 32 ; height in lines + .EQU SPRITE_STRIPES 4 ; width in words i.e. 8-pixel stripes .EQU WORDS_PER_LINE 80 .EQU FB_RA $900 @@ -65,7 +66,8 @@ CALC_VMEM_ADDR: .EQU PS_Y 16 .EQU PS_SHIFT_C 20 .EQU PS_SPILL 24 - .EQU PS_FS 28 + .EQU PS_STRIPE_C 28 + .EQU PS_FS 32 PUTSPRITE: FPADJ -PS_FS STORE PS_SPRITE_DATA @@ -160,10 +162,14 @@ PS_LOOP2_X: STOREI ; store result into i/o reg DROP - ; - ; process spilled bits and right half of sprite data - ; + ; set counter for remaining stripes + LOADC SPRITE_STRIPES - 1 + STORE PS_STRIPE_C + ; + ; process spilled bits and next vertical stripe of sprite data + ; +PS_NEXT_STRIPE: ; put spill bits on stack for later LOAD PS_SPILL @@ -176,7 +182,9 @@ PS_LOOP2_X: ; reset spill bits LOADC 0 STORE PS_SPILL - + + ; last spill bits are on ToS now + ; shift pixel data to right LOAD PS_SHIFT_C ; load shift count PS_LOOP3: ; test it for zero @@ -230,8 +238,14 @@ PS_LOOP3_X: SWAP STOREI DROP - - ; write spilled bits into next vmem word + + LOAD PS_STRIPE_C ; decrement stripe count + DEC 1 + DUP + STORE PS_STRIPE_C + CBRANCH.NZ PS_NEXT_STRIPE ; if non-zero, next stripe + + ; write spilled bits of the last stripe into next vmem word LOAD PS_SPILL ; get spill bits DUP LOADCP CALC_MASK ; calculate sprite mask for spill bits @@ -274,7 +288,8 @@ PS_L_XT: .EQU UD_S_BGDATA 12 .EQU UD_S_OFFSET 16 .EQU UD_S_BGORIG 20 - .EQU UD_S_FS 24 + .EQU UD_STRIPE_C 24 + .EQU UD_S_FS 28 UNDRAWSPRITE: FPADJ -UD_S_FS STORE UD_S_BGORIG @@ -318,25 +333,35 @@ UD_S_L1: STOREI ; reuse addr from STOREI - ; load 2nd word of background data + LOADC SPRITE_STRIPES - 1 ; set remaining stripe count + STORE UD_STRIPE_C + +UD_NEXT_STRIPE: + ; load next word of background data LOAD UD_S_BGDATA INC 4 DUP STORE UD_S_BGDATA LOADI STOREI ; and write it to vmem - DROP + ; reuse addr from STOREI - ; if pixel shift is zero, no 3rd word + LOAD UD_STRIPE_C ; decrease remaining stripe count + DEC 1 + DUP + STORE UD_STRIPE_C + CBRANCH.NZ UD_NEXT_STRIPE ; if non-zero, next stripe + + DROP ; remove addr from STOREI + + ; if pixel shift is zero, no spill word LOAD UD_S_PXS CBRANCH.Z UD_S_L2 - ; load 3rd word of background data + ; load next word of background data LOADCP FB_IO LOAD UD_S_BGDATA INC 4 - DUP - STORE UD_S_BGDATA LOADI STOREI ; and write it to vmem DROP diff --git a/examples/walking.sprt b/examples/walking.sprt new file mode 100644 index 0000000..2cdd0ce Binary files /dev/null and b/examples/walking.sprt differ diff --git a/utils/png2pict.py b/utils/png2pict.py index 73c4670..840f32c 100644 --- a/utils/png2pict.py +++ b/utils/png2pict.py @@ -2,6 +2,9 @@ import sys import png +sprite_width = 32 +sprite_height = 32 + def process_pixdata(outfile, pixdata, frameindex = 0, pix_w=640, pix_h=400): pixmask = 15 @@ -72,22 +75,20 @@ def write_pict_file(width, height, px, metadata, outfile): def write_sprite_file(width, height, px, metadata, outfile): - sprite_height=16 - print("processing as SPRT file with {} sprites...".format(height//sprite_height)) - if width != 16: - print("width must be 16, aborting") + if width != sprite_width: + print("width must be {}, aborting".format(sprite_width)) sys.exit(1) pixdata = list(px) palette = metadata['palette'] if len(palette) != 16: - print("palette must have 16 colors, aborting") + print("palette must have 16 colors instead of {}, aborting".format(len(palette))) sys.exit(0) with open(outfile,'wb') as f: write_sprite_header(f) - process_pixdata(f, pixdata, pix_w=16, pix_h=height) + process_pixdata(f, pixdata, pix_w=sprite_width, pix_h=height) if __name__ == '__main__': @@ -103,8 +104,8 @@ if __name__ == '__main__': width, height, px, metadata = p if width == 640: write_pict_file(width, height, px, metadata, outfile) - elif width == 16: + elif width == sprite_width: write_sprite_file(width, height, px, metadata, outfile) else: - print("Can't handle this file, need a width of\n640 or 16 pixels with 16 color palette.") + print("Can't handle this file, need a width of\n640 or {} pixels with 16 color palette.".format(sprite_width))