Prev: DBEB Up: Map Next: DD02
DC41: Set-up item plotting
This checks that the item is visible, and if so readies the sprite plotter for the given item. The clipped values from the visibility check are used to enable or disable portions of the inner loop to cause clipping. Note that item plotting only ever uses the 16 pixel plotter.
Note: This is the counterpart of, and very similar to, the routine at setup_vischar_plotting.
Used by the routine at plot_sprites.
Input
A Item index
IY Pointer to item_struct
Output
F Z set if item is visible, NZ otherwise
The $3F mask here looks like it ought to be $1F (item__LIMIT - 1). Potential bug: The use of A later on does not re-clamp it to $1F.
setup_item_plotting DC41 AND $3F Mask off item_FOUND
Bug: This writes the item index to saved_item but that location is never subsequently read from.
DC43 LD ($8213),A Store saved_item
DC46 PUSH IY Copy the item_struct pointer into HL
DC48 POP HL
DC49 INC HL Advance HL to item_struct.pos
DC4A INC HL
DC4B LD DE,$81B2 Copy item_struct.pos and item_struct.iso_pos to tinypos_stash and iso_pos (five contiguous bytes)
DC4E LD BC,$0005
DC51 LDIR
HL now points at global sprite_index.
DC53 EX DE,HL Point DE at item_struct.sprite_index
DC54 LD (HL),B Zero sprite_index so that items are never drawn flipped
DC55 LD HL,$DD7D Point HL at item_definitions[item] (a spritedef_t)
DC58 ADD A,A
DC59 LD C,A
DC5A ADD A,A
DC5B ADD A,C
DC5C LD C,A
DC5D ADD HL,BC
DC5E INC HL Advance HL to spritedef.height
DC5F LD A,(HL) Load it
DC60 LD ($8214),A Set item_height to spritedef.height
DC63 INC HL Advance HL to spritedef.bitmap
DC64 LD DE,$81AC Copy spritedef bitmap and mask pointers to global bitmap_pointer and mask_pointer
DC67 LD BC,$0004
DC6A LDIR
DC6C CALL item_visible Clip the item's dimensions to the game window
DC6F RET NZ Return if the item is invisible
The item is visible.
DC70 PUSH BC Preserve the lefthand skip and clipped width
DC71 PUSH DE Preserve the top skip and clipped height
Self modify the sprite plotter routines.
DC72 LD A,E Copy the clipped height into A
DC73 LD ($E2C2),A Write clipped height to the instruction at pms16_right_height_iters in plot_masked_sprite_16px (shift right case)
sip_do_enables DC76 LD A,B Is the lefthand skip zero?
DC77 AND A
DC78 JP NZ,sip_enable_is_zero Jump if not
There's no left hand skip - enable instructions.
sip_enable_is_one DC7B LD A,$77 Load A' with the opcode of 'LD (HL),A'
DC7D EX AF,AF'
DC7E LD A,C Set a counter to clipped_width. We'll write out this many bytes before clipping
DC7F JR sip_enable_cont (else)
sip_enable_is_zero DC81 XOR A Load A' with the opcode of 'NOP'
DC82 EX AF,AF'
DC83 LD A,$03 Set a counter to (3 - clipped_width). We'll clip until this many bytes have been written
DC85 SUB C
sip_enable_cont DC86 EXX Bank
DC87 LD C,A Move counter to C
DC88 EX AF,AF' Unbank the opcode we'll write`
Set the addresses in the jump table to NOP or LD (HL),A.
sip_enables_iters DC89 LD HL,$E0E0 Point HL at plot_masked_sprite_16px_enables[0]
DC8C LD B,$03 Set B for 3 iterations / 3 pairs of self modified locations
Start loop
sip_enables_loop DC8E LD E,(HL) Fetch an address
DC8F INC HL
DC90 LD D,(HL)
DC91 LD (DE),A Write a new opcode
DC92 INC HL Advance
DC93 LD E,(HL) Fetch an address
DC94 INC HL
DC95 LD D,(HL)
DC96 INC HL Advance
DC97 LD (DE),A Write a new opcode
DC98 DEC C Count down the counter
DC99 JR NZ,sip_selfmod_next Jump if nonzero
DC9B XOR $77 Swap between LD (HL),A and NOP
sip_selfmod_next DC9D DJNZ sip_enables_loop ...loop
Calculate Y plotting offset.
The full calculation can be avoided if we know there are rows to skip since in that case the sprite always starts at top of the screen.
DC9F EXX Bank
DCA0 LD A,D Is top skip zero?
DCA1 AND A
DCA2 LD DE,$0000 Initialise our Y value to zero
DCA5 JR NZ,sip_y_skip_set Jump if top skip isn't zero
DCA7 LD HL,$81BC Compute Y = iso_pos_y - map_position_y
DCAA LD A,($81B6)
DCAD SUB (HL)
DCAE LD L,A Multiply Y by the window buf stride (192) and store it in HL
DCAF LD H,$00
DCB1 ADD HL,HL
DCB2 ADD HL,HL
DCB3 ADD HL,HL
DCB4 ADD HL,HL
DCB5 ADD HL,HL
DCB6 ADD HL,HL
DCB7 LD E,L
DCB8 LD D,H
DCB9 ADD HL,HL
DCBA ADD HL,DE
DCBB EX DE,HL Move Y into DE
sip_y_skip_set DCBC LD A,($81B5) Compute x = iso_pos_x - map_position_x
DCBF LD HL,$81BB
DCC2 SUB (HL)
DCC3 LD L,A Copy x to HL and sign extend it
DCC4 LD H,$00
DCC6 JR NC,sip_x_skip_set
DCC8 LD H,$FF
sip_x_skip_set DCCA ADD HL,DE Combine the x and y values
DCCB LD DE,$F290 Add the screen buffer start address
DCCE ADD HL,DE
DCCF LD ($81A2),HL Save the finalised screen buffer pointer
DCD2 LD HL,$8100 Point HL at the mask_buffer
DCD5 POP DE Retrieve the top skip and clipped height
DCD6 PUSH DE
DCD7 LD A,D mask buffer pointer += top_skip * 4
DCD8 ADD A,A
DCD9 ADD A,A
DCDA ADD A,L
DCDB LD L,A
DCDC LD ($81B0),HL Set foreground_mask_pointer
DCDF POP DE Retrieve the top skip and clipped height (again)
DCE0 PUSH DE
DCE1 LD A,D Is top skip zero?
DCE2 AND A
DCE3 JR Z,setup_item_plotting_0 Jump if so
Bug: This loop is setup as generic multiply but only ever multiplies by two.
DCE5 LD D,A Copy top_skip to loop counter
DCE6 XOR A Zero the accumulator
DCE7 LD E,$03 Set multiplier to two (width bytes - 1)
DCE9 DEC E
Start loop
sip_mult_loop DCEA ADD A,E Accumulate
DCEB DEC D Decrement counter
DCEC JP NZ,sip_mult_loop ...loop
D will be set to zero here either way: if the loop terminates, or if jumped into.
setup_item_plotting_0 DCEF LD E,A Set DE to skip (result)
DCF0 LD HL,($81AC) Advance bitmap_pointer by 'skip'
DCF3 ADD HL,DE
DCF4 LD ($81AC),HL
DCF7 LD HL,($81AE) Advance mask_pointer by 'skip'
DCFA ADD HL,DE
DCFB LD ($81AE),HL
It's unclear as to why these values are preserved since they're not used by the caller.
DCFE POP BC Restore the lefthand skip and clipped width
DCFF POP DE Restore the top skip and clipped height
This XOR A isn't strictly needed - the Z flag should still be set from DCEC. (The counterpart at E541 doesn't have it).
DD00 XOR A Set Z flag to signal "is visible" for return
DD01 RET Return
Prev: DBEB Up: Map Next: DD02