Tiling3D 14 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54
; Copyright 2002 Tematic Ltd
;
; Licensed under the Apache License, Version 2.0 (the "License");
; you may not use this file except in compliance with the License.
; You may obtain a copy of the License at
;
;     http://www.apache.org/licenses/LICENSE-2.0
;
; Unless required by applicable law or agreed to in writing, software
; distributed under the License is distributed on an "AS IS" BASIS,
; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
; See the License for the specific language governing permissions and
; limitations under the License.
;
;
; MB 23/3/98
; Complete reimplementation of tiling code based on 3DPatch sources
;

;-------------------------------------------------------------------------------
;			  Window background drawing code
;-------------------------------------------------------------------------------

		DCB	"MIB",0

; this is a 'signed' division macro

        MACRO
$lab    DivRemS $ra,$rb,$rc,$tmp
$lab    CMP     $rb,#0
        BLT     %FT2
        DivRem  $ra,$rb,$rc,$tmp
        B       %FT4
2       RSB     $rb,$rb,#0
        DivRem  $ra,$rb,$rc,$tmp
        RSB     $rb,$rb,#0
        ; modulus should be -ve if divisor is -ve
4
        MEND

; plotspritebackground
;
; plot the textured background in a window
;
;	 on entry : 	r0 = window background colour
;	 		r6-r9 = window visible area coords
;	 		r10 = internal window block pointer
;
;	on exit:	all regs preserved
;
		ROUT
plotspritebackground
		Push	"r0-r5,lr"

Robert Sprowson's avatar
Robert Sprowson committed
55
		Debug	tiling,"Entering plotspritebackground",r0,r6,r7,r8,r9,r10
56 57 58 59 60 61 62 63 64 65 66

		cmp	r0,#15
		bhi	%FT02

	[ TrueIcon3
		ldrb	r14,[handle,#w_flags2]		; if using true colours for window backgrounds and this window has a custom
		tst	r14,#wf2_truecolour		; background colour then don't plot a tile, just clear the background
		bne	%FT02
	]
		mov	r5,r0				; r5 = window bg colour

Robert Sprowson's avatar
Robert Sprowson committed
67 68 69 70 71 72
		ldr	r0,iconbarhandle
		Abs	r0,r0
		teq	r0,handle
		moveq	r5,#17				; if the current window is the iconbar try tile_i
		beq	%FT01

73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153
		ldr	r0,[handle,#w_taskhandle]
		cmp	r0,#-1				; if the current window is a menu
		bne	%FT01

		ldr	r1,ThreeDFlags
		tst	r1,#ThreeDFlags_TexturedMenus	; check if menu textures are enabled
		beq	%FT02
		tst	r1,#ThreeDFlags_UseAlternateMenuTexture ; then check which texture to use
		movne	r5,#16
		moveq	r5,#1

01
		Debug	tiling,"Calling TileWindowBackground"
		bl	TileWindowBackground
;		Debug	tiling,"Calling PlotWindowBorders"
;		bl	PlotWindowBorders

		Pull	"r0-r5,PC"

02
		swi	OS_WriteI + 16
		Pull	"r0-r5,PC"

ploticonbackgroundsprite
		Push	"r0-y1,lr"

		ldr	x0,thisCBptr
		ldr	y0,spritename
		ldr	x1,lengthflags
		Push	"x0-x1"

		adr	r14,clipx0
		ldmia	r14,{x0-y1}
		Push	"x0-y1"			; save the current clipping rectangle

		CMP	x0,cx0
		MOVLT	x0,cx0
		CMP	y0,cy0
		MOVLT	y0,cy0
		CMP	x1,cx1
		MOVGT	x1,cx1
		CMP	y1,cy1
		MOVGT	y1,cy1

		CMP	x0,x1
		CMPLT	y0,y1
		ADDGE	sp,sp,#7*4
		Pull	"r0-y1,pc",GE

		Debug	tiling,"In ploticonbackgroundsprite, about to set graphics window to : ",x0,y0,x1,y1
		BL	graphicswindow

		LDRB	r0,[handle,#w_wbcol]

		ADD	r14,handle,#w_wax0
		LDMIA	r14,{x0-y1}

		SWI	OS_WriteI + 16
		BL	plotspritebackground

		Pull	"x0-y1"
		BL	graphicswindow

		Pull	"x0-x1"
		str	x0,thisCBptr
		str	y0,spritename
		str	x1,lengthflags

		Pull	"r0-y1,pc"

tile_1		DCB	"tile_1",0
		ALIGN

TileWindowBackground
		ROUT
		Push	"r6-r11,lr"

		ldr	r1,[handle,#w_areaCBptr]
		cmp	r1,#2
		blo	%FT00

154
		teq	r5,#sc_verylightgrey
155 156 157
		bne	%FT00

		adr	r2,tile_1
158
		mov	r0,#SpriteReason_SelectSprite :OR: 256
159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179
		swi	XOS_SpriteOp
		bvs	%FT00

		adrl	r8,temp_tile_sprite
		bl	get_tile_sprite_info
		bvs	%FT00

		Debug	tiling,"Calling tile_sprite_fill_area"
		bl	tile_sprite_fill_area

		ldr	r2,[r8,#TileInfo_TranslationTablePtr]
		cmp	r2,#0
		movne	r0,#ModHandReason_Free
		blne	XROS_Module
		mov	r2,#0
		str	r2,[r8,#TileInfo_TranslationTablePtr]

		CLRV
		Pull	"r6-r11,PC"

00		adrl	r8,tile_sprites
180
		ASSERT	TileInfo = 36
181
		add	r0,r5,r5,LSL #3
182
		mov	r0,r0,LSL #2			; r0 = r5 * sizeof(TileInfo)
183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312
		add	r8,r8,r0			; r8 = ptr to correct sprite info block

		bl	get_tile_sprite			; r8 = ptr to filled in sprite info block

		blvc	tile_sprite_fill_area

   		Pull	"r6-r11,PC",VC

01		swi	XOS_WriteI + 16			; clear the screen
		CLRV
		Pull	"r6-r11,PC"

PlotWindowBorders
		ROUT
;		 on entry: r6-r9 = window visible area
;		 	     r10 = internal window block pointer
		ROUT
		Push	"r3-r5,x0-y1,lr"

		ldr	r14,ThreeDFlags
		tst	r14,#ThreeDFlags_Use3DBorders
		Pull	"r3-r5,x0-y1,pc",EQ

		ldrb	r5,[handle,#w_wbcol]

		ldr	r3,truefacecolour
		ldr	r4,trueoppcolour
		Push	"r3,r4"

		ldr	r3,iconbarhandle
		Abs	r3,r3			; convert to internal block pointer
		teq	r3,handle
		beq	%FT01

		ldr	r3,[handle,#w_taskhandle]	; check for menu
		cmp	r3,#-1
		bne	%FT04

		tst	r14,#ThreeDFlags_UseAlternateMenuTexture ; see if we need to use the window border colours or the menu colours
		beq	%FT03

		ldr	r3,truemenuborderfacecolour		; set up the menu border colours
		ldr	r4,truemenuborderoppcolour
		str	r3,truefacecolour
		str	r4,trueoppcolour
		b	%FT00

04		teq	r5,#1					; check if this window needs a border
		bne	%FT02

		ldrb	r14,[handle,#w_flags2]
		and	r14,r14,#wf2_no3Dborder :OR: wf2_force3Dborder
		teq	r14,#wf2_no3Dborder
		beq	%FT02
		teq	r14,#wf2_force3Dborder
		beq	%FT03

		ldr	r14,[handle,#w_flags]
		tst	r14,#&70000000
		tsteq	r14,#&00000020
 [ No3DChildWindows
		ldreq	r14,[handle,#w_parent]
		cmpeq	r14,#-1				; check if it's a top level window
 ]
		bne	%FT02

03		ldr	r3,truewindowborderfacecolour	; set up the window borders colours
		ldr	r4,truewindowborderoppcolour
		str	r3,truefacecolour
		str	r4,trueoppcolour

00		bl	plot_slabout

		ldr	r0,truefgcolour
		cmp	r0,#-1
		beq	%FT02
		ldr	r3,ditheringflag
		mov	r4,#0
		swi	XColourTrans_SetGCOL		; put the forground colour back the way it was before we plotted the border
02
		Pull	"r3,r4"
		str	r3,truefacecolour
		str	r5,trueoppcolour

		Pull	"r3-r5,x0-y1,pc"

01		tst	r14,#ThreeDFlags_Fully3DIconBar
		subeq	x0,x0,#16		; move the ends off the screen
		addeq	x1,x1,#16		; not the best way to do it, but the smallest...
		b	%BT03

write_tile_sprite_name_bpp
		; on entry: r5 = bpp to add to the end of the sprite name
		;	    r7 = ptr to end of base sprite name
		;  on exit: string updated to add bpp to end
		ROUT
		Push	"r0-r2,lr"
		mov	r1,r7
		mov	r0,#'-'
		strb	r0,[r1],#1
		mov	r0,r5
		cmp	r0,#16
		movhi	r2,#'3'
		movhi	r0,#2
		moveq	r2,#'1'
		moveq	r0,#6
		strhsb	r2,[r1],#1
		add	r0,r0,#'0'
		strb	r0,[r1],#1
		mov	r0,#0
		strb	r0,[r1,#0]
		Pull	"r0-r2,pc"

tile		DCB	"tile"

get_base_tile_sprite_name
		ROUT
		; on entry: r5 = window bg colour
		;	    r6 = ptr to memory block to put sprite name in
		;  on exit: memory at sp updated to contain the sprite name
		;	    r7 = ptr to terminating NUL
		Push	"r0,lr"
		mov	r7,r6				; r7 = ptr to memory to hold name
		ldr	r0,tile
		str	r0,[r7],#4
		mov	r0,#'_'
		strb	r0,[r7],#1			; now contains 'tile_

		teq	r5,#16
		moveq	r0,#'m'
Robert Sprowson's avatar
Robert Sprowson committed
313 314 315 316 317
		beq	%F00				; it's a menu, so produce 'tile_m'

		teq	r5,#17
		moveq	r0,#'i'
		beq	%F00				; it's the iconbar, so produce 'tile_i'
318 319 320 321 322 323 324

		cmp	r5,#10
		movhs	r0,#'1'
		strhsb	r0,[r7],#1			; >= to 10 so put in the 1 'tile_1'
		addhs	r0,r5,#'0'-10			; and set r0 to the second character of the number
		addlo	r0,r5,#'0'			; else r0 = the single digit number

Robert Sprowson's avatar
Robert Sprowson committed
325 326
00		strb	r0,[r7],#1
		mov	r0,#0				; finished, so terminate the name
327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346
		strb	r0,[r7,#0]

		Pull	"r0,pc"

get_tile_sprite_info
;	on entry:	r1 = sprite area pointer
;			r2 = sprite pointer
;			r8 = ptr to tile info block
;	one exit:       block at r8 filled in
;                       or V set for error
		Push	"r0-r4,lr"

		str	r1,[r8,#TileInfo_SpriteAreaPtr]
		str	r2,[r8,#TileInfo_SpritePtr]

		str	r1,thisCBptr
		str	r2,spritename
		mov	r0,#0
		str	r0,lengthflags
		bl	cachespritedata
347 348
		movvc	r1,#0
		blvc	cachespritepixtable
349 350 351 352 353 354 355 356 357 358 359
		movvs	r0,#-1
		strvs	r0,[r8,#TileInfo_SpritePtr]
		Pull	"r0-r4,pc",VS

		ldr	r0,sprite_log2px
		mov	r3,r3,LSL r0
		str	r3,[r8,#TileInfo_Width]
		ldr	r0,sprite_log2py
		mov	r4,r4,LSL r0
		str	r4,[r8,#TileInfo_Height]

360
		ldrb	r0,sprite_needsfactors
361 362 363 364
		teq	r0,#0

		moveq	r0,#-1						; if the scale factors are not needed then the first one is -1

365
		adrne	r14,sprite_factors
366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406
		ldmneia	r14,{r0-r3}

		add	r14,r8,#TileInfo_ScaleFactors
		stmia	r14,{r0-r3}

		ldr	r0,pixtable_at
		str	r0,[r8,#TileInfo_TranslationTablePtr]
		mov	r0,#0
		str	r0,pixtable_at

		Pull	"r0-r4,pc"

find_tile_sprite
;	on entry:	r6 = ptr to sprite name
;			r8 = ptr to info block to fill in
;	on exit:	block at r8 updated
;			or V set if sprite could not be found
		ROUT
		Push	"r0-r3,lr"

		DebugS	tiling,"Looking for sprite : ",r6
		b	%FT02

		ldr	r0,list_at
		teq	r0,#0				; if the cached sprite list does not exist
		beq	%FT02				; do the lookup the slow way

		str	r6,spritename
		bl	getspriteaddr
		ldrvc	r1,baseofsprites

00		movvs	r2,#-1
		strvs	r2,[r8,#TileInfo_SpritePtr]
		Pull	"r0-r3,pc",VS

01
                Debug	tiling,"Sprite found at :",r1,r2
		bl	get_tile_sprite_info

		Pull	"r0-r3,pc"

407
02		mov     r0,#SpriteReason_SelectSprite :OR: 256
408 409 410 411 412 413 414 415 416 417 418
      	    [ SpritePriority
        	ldr     r1,baseofhisprites
      	    |
       	 	ldr     r1,baseofsprites
      	    ]
		mov	r2,r6
		mov	r3,sp
        	swi     XOS_SpriteOp
		mov	r3,sp
        	bvc     %BT01

419
        	mov     r0,#SpriteReason_SelectSprite :OR: 256
420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442
      	    [ SpritePriority
        	ldr     r1,baseoflosprites
            |
        	ldr     r1,baseofromsprites
            ]
		mov	r2,r6
		mov	r3,sp
        	swi     XOS_SpriteOp
		mov	r3,sp
        	bvc     %BT01

		b	%BT00

find_tile_sprite_all_depths
;	on entry:	r5 = window bg colour
;			r6 = ptr to memory block rto put sprite name in
;			r7 = ptr to end of tile_## string
;			r8 = ptr to tile info block to fill in
;			stack contains base sprite name
;	on exit:	block at r8 updated
;			or V set if no sprite could be found
		ROUT
		Push	"r5,lr"
Robert Sprowson's avatar
Robert Sprowson committed
443
00
444 445
		ldr	r5,log2bpp
		mov	r14,#1
Robert Sprowson's avatar
Robert Sprowson committed
446
		mov	r5,r14,LSL r5			; r5 = bpp of current screen mode
447

Robert Sprowson's avatar
Robert Sprowson committed
448
05		bl	write_tile_sprite_name_bpp
449 450 451 452 453
		bl	find_tile_sprite
		Pull	"r5,pc",VC

		mov	r5,r5,LSR #1
		cmp	r5,#8
Robert Sprowson's avatar
Robert Sprowson committed
454
		bhs	%BT05				; if no match for current bpp, only search to 8bpp (no lower)
455 456

		mov	r5,#0
Robert Sprowson's avatar
Robert Sprowson committed
457
		strb	r5,[r7,#0]			; failed to find any variant of the sprite so try the base name
458
		bl	find_tile_sprite
Robert Sprowson's avatar
Robert Sprowson committed
459 460 461 462 463 464 465
		Pull	"r5,pc",VC

		ldrb	r5,[r7,#-1]
		teq	r5,#'i'				; tile_i is optional
		moveq	r5,#'1'				; have another go but with tile_1 instead
		streqb	r5,[r7,#-1]
		beq	%BT00
466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512

		Pull	"r5,pc"

get_tile_sprite	ROUT
		; on entry: r5 = window bg colour
		; 	    r8 = ptr to sprite info block to fill in
		;  on exit: block at r8 updated
		;	    V set if sprite not found
		Push	"r0-r7,lr"

00		ldr	r0,[r8,#TileInfo_SpritePtr]
		cmp	r0,#0
                beq     %FT01				; if sprite pointer is != 0 then the sprite has already been
                cmp     r0,#-1
		Pull	"r0-r7,pc",NE			; if not 0 or -1 then return now with V clear
		cmn     r0,#1:SHL:31
		Pull    "r0-r7,pc"			; if it is -1 then return with V set to cause the screen to just
							; be cleared
01
		mov	r0,#161				; check if tiling is disabled in CMOS
		mov	r1,#&8C
		swi	XOS_Byte
		tst	r2,#128
		SETV	NE
		movvs	r0,#-1
		strvs	r0,[r8,#TileInfo_SpritePtr]
		Pull	"r0-r7,pc",VS

		sub	sp,sp,#16

		mov	r6,sp
		bl	get_base_tile_sprite_name
		DebugS	tiling,"Base sprite name : ",r6
		bl	find_tile_sprite_all_depths

		add	sp,sp,#16

		Pull	"r0-r7,pc"

tile_sprite_fill_area
		ROUT
		; on entry: r8  = ptr to sprite info block

		Push	"r0-r11,lr"

		mov	r11,r8

513 514 515 516 517 518 519 520 521 522 523 524
		ldr	r0,=SpriteReason_TileSpriteScaled+512
		ldr	r1,[r11,#TileInfo_SpriteAreaPtr]
		ldr	r2,[r11,#TileInfo_SpritePtr]
		ldr	r3,[handle,#w_scx]
		ldr	r6,[handle,#w_wax0]
		ldr	r4,[handle,#w_scy]
		ldr	r7,[handle,#w_way1]
		sub	r3,r6,r3
		sub	r4,r7,r4
		mov	r5,#0
		bl	plot_tile

525
	[ CanTileManually
526 527 528 529
		; Fall black to plotting the tiles manually if the above call
		; failed due to OS_SpriteOp 65 not being available
		bvc	%ft90
		ldr	r0,[r0]
530
		ldr	r1,=ErrorNumber_Sprite_BadReasonCode
531 532 533
		teq	r0,r1
		bne	%ft90

534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565
		ldr	x0,[handle,#w_wax0]
		ldr	r0,[handle,#w_scx]
		ldr	r3,[r11,#TileInfo_Width]
		DivRemS	x1,r0,r3,r5
		sub	x0,x0,r0		; x0 = x tiling start point

		ldr	y1,[handle,#w_way1]
		ldr	r0,[handle,#w_scy]
		ldr	r4,[r11,#TileInfo_Height]
		DivRemS	x1,r0,r4,r5
		sub	y1,y1,r0		; y1 = y tiling start point

                adr	r14,clipx0
		ldmia	r14,{r0,y0,x1,r14}

		sub	y0,y0,#1
		sub	y0,y0,r4		; move min y down one whole tile

		sub	r0,r0,#1
		add	x1,x1,#1
		add	r14,r14,#1

00		cmp	y1,r14			; get y1 inside clipping rectangle
		subgt	y1,y1,r4
		bgt	%BT00

01		cmp	x0,r0			; get x0 inside clipping rectangle
		addlt	x0,x0,r3
		blt	%BT01

		sub	x0,x0,r3		; move it back over the left edge of the window

566
		mov	r0,#SpriteReason_PutSpriteScaled+512
567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582
		ldr	r1,[r11,#TileInfo_SpriteAreaPtr]
		ldr	r2,[r11,#TileInfo_SpritePtr]
		mov	r5,#0

		mov	r10,r4			; r10 = tile height
		mov	r4,y1
		mov	r9,r3			; r9 (y1) = tile width

02		mov	r3,x0			; r3 = start x pos
03		bl	plot_tile
		add	r3,r3,r9		; move right one tile
		cmp	r3,x1			; if more tiles on right
		blt	%BT03			; keep going
		sub	r4,r4,r10		; move down one tile
		cmp	r4,y0			; if more tiles below
		bgt	%BT02			; keep going
583
90
584
	] ; CanTileManually
585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602

		Pull	"r0-r11,pc"

plot_tile	ROUT
;	on entry:	r0,r1,r2 - as for OS_SpriteOp 52
;			r3 = x coord
;			r4 = y coord
;			r5 = plot action
;	on exit:	r0-r4 preserved
		Push	"r6,r7,lr"
		ldr	r6,[r11,#TileInfo_ScaleFactors + 0]
		cmp	r6,#-1
		moveq	r6,#0
		addne	r6,r11,#TileInfo_ScaleFactors
		ldr	r7,[r11,#TileInfo_TranslationTablePtr]
		swi	XOS_SpriteOp
		Pull	"r6,r7,pc"

603
reset_all_tiling_sprites ROUT
604 605
		; on entry R0 = the value to write to all tile sprite pointers
		; all tile sprite pointers are updated and all translation tables freed
606
		Push	"r0-r4,lr"
607

608 609
		mov	r1,r0
		Debug	tiling, "Reset tiling to", r1
610

611
		adrl	r3,tile_sprites
612
		add	r4,r3,#tile_sprites_end - tile_sprites
613

614
00		str	r1,[r3,#TileInfo_SpritePtr]			; set the sprite pointer
615

616
		ldr	r2,[r3,#TileInfo_TranslationTablePtr]
617 618 619 620 621
		teq	r2,#0						; if the table is non zero then free it
		movne	r0,#ModHandReason_Free
		blne	XROS_Module

		mov	r2,#0
622
		str	r2,[r3,#TileInfo_TranslationTablePtr]		; the table no longer exists so set the pointer to 0
623

624 625 626
		add	r3,r3,#TileInfo					; move on to the next one
		cmp	r3,r4
		bcc	%BT00
627

628
		Pull	"r0-r4,pc"                                      ; exit with V clear
629 630

		END