; Compile a stamp into a compilation cache _CompileStamp _lines equ tmp0 _width0 equ tmp1 _width equ tmp2 baseAddr equ tmp3 destAddr equ tmp4 vbuffAddr equ tmp5 lda _Sprites+SPRITE_HEIGHT,x sta _lines lda _Sprites+SPRITE_WIDTH,x ; Width in bytes (4 or 8) lsr sta sta _width0 lda _Sprites+SPRITE_DISP,x ; Get the address of the stamp sta vbuffAddr tax ldy CompileBankTop ; First free byte in the compilation bank phb pei CompileBank plb plb ; Set the bank to the compilation cache stz baseAddr stz destAddr :oloop lda _width0 sta _width :iloop ldal spritemask,x beq :no_mask ; If Mask == $0000, then it's a solid word cmp #$FFFF beq :next ; If Mask == $FFFF, then it's transparent ; Mask with the screen data lda #LDA_ABS_X_OPCODE sta: 0,y lda destAddr sta: 1,y sta: 10,y lda #AND_IMM_OPCODE sta: 3,y ldal spritemask,x sta: 4,y lda #ORA_IMM_OPCODE sta: 6,y ldal spritedata,x sta: 7,y lda #STA_ABS_X_OPCODE sta: 9,y tya adc #12 tay bra :next ; Just store the data :no_mask lda #LDA_IMM_OPCODE sta: 0,y ldal spritedata,x sta: 1,y lda #STA_ABS_X_OPCODE sta: 3,y lda destAddr sta: 4,y tya adc #6 tay :next inx inx inc destAddr ; Move to the next word inc destAddr dec _width bne :iloop lda vbuffAddr adc #SPRITE_PLANE_SPAN sta vbuffAddr tax lda baseAddr ; Move to the next line adc #160 sta baseAddr sta destAddr dec lines bne :oloop lda #RTL_OPCODE ; Finish up the subroutine sta: 0,y iny sty CompileBankTop plb rts ; Draw a sprite directly to the graphics screen. If sprite is clipped at all, do not draw. ; ; X = sprite record index _DSTSOut rts _DrawStampToScreen lda _Sprites+IS_OFF_SCREEN,x ; If the sprite is off-screen, don't draw it bne _DSTSOut lda _Sprites+SPRITE_CLIP_WIDTH,x ; If the sprite is clipped to the playfield, don't draw it cmp _Sprites+SPRITE_WIDTH,x bne _DSTSOut lda _Sprites+SPRITE_CLIP_HEIGHT,x cmp _Sprites+SPRITE_HEIGHT,x bne _DSTSOut clc lda _Sprites+SPRITE_Y,x adc ScreenY0 asl asl asl asl asl sta tmp0 asl asl clc adc tmp0 clc adc #$2000 clc adc ScreenX0 adc _Sprites+SPRITE_X,x ; Move to the horizontal address tay ; This is the on-screen address lda _Sprites+SPRITE_HEIGHT,x sta tmp0 ; Sprite is either 8 or 16 pixels wide, so select the entry point lda _Sprites+SPRITE_WIDTH,x cmp #4 beq :skinny lda _Sprites+SPRITE_DISP,x ; This is the VBUFF address with the correct sprite frame tax phb pea $0101 plb plb bra :entry16 :loop16 clc txa adc #SPRITE_PLANE_SPAN tax tya adc #SHR_LINE_WIDTH tay :entry16 lda: 6,y andl spritemask+6,x oral spritedata+6,x sta: 6,y lda: 4,y andl spritemask+4,x oral spritedata+4,x sta: 4,y lda: 2,y andl spritemask+2,x oral spritedata+2,x sta: 2,y lda: 0,y andl spritemask+0,x oral spritedata+0,x sta: 0,y dec tmp0 bne :loop16 plb rts :skinny lda _Sprites+SPRITE_DISP,x ; This is the VBUFF address with the correct sprite frame tax phb pea $0101 plb plb bra :entry8 :loop8 clc txa adc #SPRITE_PLANE_SPAN tax tya adc #SHR_LINE_WIDTH tay :entry8 lda: 2,y andl spritemask+2,x oral spritedata+2,x sta: 2,y lda: 0,y andl spritemask+0,x oral spritedata+0,x sta: 0,y dec tmp0 bne :loop8 plb rts ; Alternate entry point that takes arguments in registers instead of using a _Sprite ; record ; ; Y = VBUFF address ; X = Tile Data address ; A = Sprite Flags DISP_VFLIP equ $0004 ; hard code these because they are internal values DISP_HFLIP equ $0002 DISP_MASK equ $0018 ; Preserve the size bits _DrawSpriteStamp sty tmp1 stx tmp2 xba and #DISP_MASK ; dispatch to all of the different orientations sta tmp3 phb pea #^tiledata ; Set the bank to the tile data plb ; X = sprite ID ; Y = Tile Data ; A = VBUFF address ldx tmp3 ldy tmp2 lda tmp1 jsr _DrawSprite lda tmp3 ora #DISP_HFLIP tax ldy tmp2 lda tmp1 clc adc #3*4 jsr _DrawSprite lda tmp3 ora #DISP_VFLIP tax ldy tmp2 lda tmp1 clc adc #6*4 jsr _DrawSprite lda tmp3 ora #DISP_HFLIP+DISP_VFLIP tax ldy tmp2 lda tmp1 clc adc #9*4 jsr _DrawSprite ; Restore bank plb ; pop extra byte plb rts ; ; X = _Sprites array offset _DrawSprite jmp (draw_sprite,x) draw_sprite dw draw_8x8,draw_8x8h,draw_8x8v,draw_8x8hv ; 8 wide x 8 tall dw draw_8x16,draw_8x16h,draw_8x16v,draw_8x16hv ; 8 wide x 16 tall dw draw_16x8,draw_16x8h,draw_16x8v,draw_16x8hv ; 16 wide by 8 tall dw draw_16x16,draw_16x16h,draw_16x16v,draw_16x16hv ; 16 wide by 16 tall dw :rtn,:rtn,:rtn,:rtn ; hidden bit is set dw :rtn,:rtn,:rtn,:rtn dw :rtn,:rtn,:rtn,:rtn dw :rtn,:rtn,:rtn,:rtn :rtn rts draw_8x8 tax jmp _DrawTile8x8 draw_8x8h tax clc tya adc #64 tay jmp _DrawTile8x8 draw_8x8v tax jmp _DrawTile8x8V draw_8x8hv tax clc tya adc #64 tay jmp _DrawTile8x8V draw_8x16 tax jsr _DrawTile8x8 clc txa adc #{8*SPRITE_PLANE_SPAN} tax tya adc #{128*32} ; 32 tiles to the next vertical one, each tile is 128 bytes tay jmp _DrawTile8x8 draw_8x16h tax clc tya adc #64 tay jsr _DrawTile8x8 clc txa adc #{8*SPRITE_PLANE_SPAN} tax tya adc #{128*32} ; 32 tiles to the next vertical one, each tile is 128 bytes tay jmp _DrawTile8x8 draw_8x16v clc tax tya pha adc #{128*32} tay jsr _DrawTile8x8V clc txa adc #{8*SPRITE_PLANE_SPAN} tax ply jmp _DrawTile8x8V draw_8x16hv clc tax tya adc #64 pha adc #{128*32} tay jsr _DrawTile8x8V clc txa adc #{8*SPRITE_PLANE_SPAN} tax ply jmp _DrawTile8x8V draw_16x8 tax jsr _DrawTile8x8 clc txa adc #4 tax tya adc #128 ; Next tile is 128 bytes away tay jmp _DrawTile8x8 draw_16x8h clc tax tya adc #64 pha adc #128 tay jsr _DrawTile8x8 txa adc #4 tax ply jmp _DrawTile8x8 draw_16x8v tax jsr _DrawTile8x8V clc txa adc #4 tax tya adc #128 tay jmp _DrawTile8x8V draw_16x8hv clc tax tya adc #64 pha adc #128 tay jsr _DrawTile8x8V txa adc #4 tax ply jmp _DrawTile8x8V ; X = sprite ID ; Y = Tile Data ; A = VBUFF address draw_16x16 clc tax jsr _DrawTile8x8 txa adc #4 tax tya adc #128 tay jsr _DrawTile8x8 txa adc #{8*SPRITE_PLANE_SPAN}-4 tax tya adc #{128*{32-1}} tay jsr _DrawTile8x8 txa adc #4 tax tya adc #128 tay jmp _DrawTile8x8 draw_16x16h clc tax tya adc #64 pha adc #128 tay jsr _DrawTile8x8 txa adc #4 tax ply jsr _DrawTile8x8 txa adc #{8*SPRITE_PLANE_SPAN}-4 tax tya adc #{128*32} pha adc #128 tay jsr _DrawTile8x8 txa adc #4 tax ply jmp _DrawTile8x8 draw_16x16v clc tax tya pha ; store some copies phx pha adc #{128*32} tay jsr _DrawTile8x8V txa adc #{8*SPRITE_PLANE_SPAN} tax ply jsr _DrawTile8x8V pla adc #4 tax lda 1,s adc #{128*{32+1}} tay jsr _DrawTile8x8V txa adc #{8*SPRITE_PLANE_SPAN} tax pla adc #128 tay jmp _DrawTile8x8V draw_16x16hv clc tax tya pha adc #{128*{32+1}}+64 ; Bottom-right source to top-left tay jsr _DrawTile8x8V txa adc #4 tax lda 1,s adc #{128*32}+64 tay jsr _DrawTile8x8V txa adc #{8*SPRITE_PLANE_SPAN}-4 tax lda 1,s adc #128+64 tay jsr _DrawTile8x8V txa adc #4 tax pla adc #64 tay jmp _DrawTile8x8V ; X = sprite vbuff address ; Y = tile data pointer _DrawTile8x8 _CopyTile8x8 ]line equ 0 lup 8 lda: tiledata+32+{]line*4},y stal spritemask+{]line*SPRITE_PLANE_SPAN},x lda: tiledata+{]line*4},y stal spritedata+{]line*SPRITE_PLANE_SPAN},x lda: tiledata+32+{]line*4}+2,y stal spritemask+{]line*SPRITE_PLANE_SPAN}+2,x lda: tiledata+{]line*4}+2,y stal spritedata+{]line*SPRITE_PLANE_SPAN}+2,x ]line equ ]line+1 --^ rts _DrawTile8x8V _CopyTile8x8V ]line equ 0 lup 8 lda: tiledata+32+{{7-]line}*4},y stal spritemask+{]line*SPRITE_PLANE_SPAN},x lda: tiledata+{{7-]line}*4},y stal spritedata+{]line*SPRITE_PLANE_SPAN},x lda: tiledata+32+{{7-]line}*4}+2,y stal spritemask+{]line*SPRITE_PLANE_SPAN}+2,x lda: tiledata+{{7-]line}*4}+2,y stal spritedata+{]line*SPRITE_PLANE_SPAN}+2,x ]line equ ]line+1 --^ rts