Prev: E40F Up: Map Next: E542
E420: Set-up vischar plotting
This checks that the vischar is visible, and if so readies the sprite plotter for the given vischar. The clipped values from the visibility check are used to enable or disable portions of the inner loop to cause clipping.
Note: This is the counterpart of, and very similar to, the routine at setup_item_plotting.
Used by the routine at plot_sprites.
Input
HL Pointer to visible character
IY Pointer to visible character
Output
F Z set if vischar is visible, NZ otherwise
setup_vischar_plotting E420 LD A,$0F Advance HL to vischar.mi.pos
E422 ADD A,L
E423 LD L,A
E424 LD DE,$81B2 Point DE at tinypos_stash
E427 LD A,($68A0) Fetch the global current room index
E42A AND A Are we outdoors?
E42B JR Z,svp_outdoors Jump if so
Indoors.
Copy vischar.mi.pos.* to tinypos_stash with narrowing.
E42D LDI Copy vischar.mi.pos to tinypos_stash (narrowing each element to a byte wide)
E42F INC L
E430 LDI
E432 INC L
E433 LDI
E435 INC L
E436 JR svp_tinypos_set (else)
Outdoors.
Copy vischar.mi.pos.* to tinypos_stash with scaling.
svp_outdoors E438 LD A,(HL) Fetch vischar.mi.pos.x
E439 INC L
E43A LD C,(HL)
E43B CALL divide_by_8_with_rounding Divide (C,A) by 8 with rounding. Result is in A
E43E LD (DE),A Store the result as tinypos_stash.x
E43F INC L Advance HL to vischar.mi.pos.y
E440 INC DE Advance DE to tinypos_stash.y
E441 LD B,$02 Set B for two iterations
svp_pos_loop E443 LD A,(HL) Fetch vischar.mi.pos.y or .height
E444 INC L
E445 LD C,(HL)
E446 CALL divide_by_8 Divide (C,A) by 8 (with no rounding). Result is in A
E449 LD (DE),A Store the result as tinypos_stash.y or .height
E44A INC L Advance to the next vischar.mi.pos field
E44B INC DE Advance to the next tinypos_stash field (then finally to iso_pos - used later)
E44C DJNZ svp_pos_loop ...loop
svp_tinypos_set E44E LD C,(HL) Load vischar.mi.sprite (a pointer to a spritedef_t) and stack it
E44F INC L
E450 LD B,(HL)
E451 PUSH BC
E452 INC L Advance HL to vischar.mi.sprite_index
E453 LD A,(HL) Load it
E454 LD ($81B7),A Save global sprite_index and left/right flip flag
E457 EX AF,AF' Bank it too
E458 INC L Advance HL to vischar.iso_pos
Scale down iso_pos.*
E459 LD B,$02 Set B for two iterations
svp_isopos_loop E45B LD A,(HL) Fetch vischar.iso_pos.x/y
E45C INC L
E45D LD C,(HL)
E45E CALL divide_by_8 Divide (C,A) by 8 (with no rounding). Result is in A
E461 LD (DE),A Write the result to state.iso_pos.*
E462 INC L Advance HL to the next vischar.iso_pos element
E463 INC DE Advance DE to the next state.iso_pos element
E464 DJNZ svp_isopos_loop ...loop
E466 EX AF,AF' Unbank sprite index
E467 POP DE Restore sprite pointer
E468 ADD A,A Multiply A by six (width of a spritedef_t)
E469 LD C,A
E46A ADD A,A
E46B ADD A,C
E46C ADD A,E Add onto sprite base pointer
E46D LD E,A
E46E JR NC,svp_sprptr_ready
E470 INC D
svp_sprptr_ready E471 INC L Skip over vischar.room and unused bytes
E472 INC L
E473 EX DE,HL Put sprite pointer into DE
E474 LDI Copy spritedef width in bytes to vischar
E476 LDI Copy spritedef height in rows to vischar
E478 LD DE,$81AC Copy spritedef bitmap and mask pointers to global bitmap_pointer and mask_pointer
E47B LD BC,$0004
E47E LDIR
E480 CALL vischar_visible Clip the vischar's dimensions to the game window
E483 AND A Is it visible?
E484 RET NZ Return if not [RET NZ would do]
The vischar is visible.
E485 PUSH BC Preserve the lefthand skip and clipped width
E486 PUSH DE Preserve the top skip and clipped height
Self modify the sprite plotter routines.
E487 LD A,(IY+$1E) Fetch vischar.width_bytes to check its width
E48A CP $03 Is it 3? (3 => 16 pixels wide, 4 => 24 pixels wide)
E48C JR NZ,svp_24_wide Jump if 24 wide
svp_16_wide E48E LD A,E Copy the clipped height into A
E48F LD ($E2C2),A Write clipped height to the instruction at pms16_right_height_iters in plot_masked_sprite_16px (shift right case)
E492 LD ($E363),A Write clipped height to the instruction at pms16_left_height_iters in plot_masked_sprite_16px (shift left case)
E495 LD A,$03 Set for three enables
E497 LD HL,$E0E0 Point HL at plot_masked_sprite_16px_enables
E49A JR svp_do_enables (else)
svp_24_wide E49C LD A,E Copy the clipped height into A
E49D LD ($E121),A Write clipped height to the instruction at pms24_right_height_iters in plot_masked_sprite_24px (shift right case)
E4A0 LD ($E1E2),A Write clipped height to the instruction at pms24_left_height_iters in plot_masked_sprite_24px (shift left case)
E4A3 LD A,$04 Set for four enables
E4A5 LD HL,$E0EC Point HL at plot_masked_sprite_24px_enables
svp_do_enables E4A8 PUSH HL Preserve enables pointer
E4A9 LD ($E4C0),A Write enable count to the instruction at svp_enables_iters (self modify) and keep a copy
E4AC LD E,A
E4AD LD A,B Is the lefthand skip zero?
E4AE AND A
E4AF JR NZ,svp_enable_is_zero Jump if not
There's no left hand skip - enable instructions.
svp_enable_is_one E4B1 LD A,$77 Load A' with the opcode of 'LD (HL),A'
E4B3 EX AF,AF'
E4B4 LD A,C Set a counter to clipped_width. We'll write out this many bytes before clipping
E4B5 JR svp_enable_cont (else)
svp_enable_is_zero E4B7 XOR A Load A' with the opcode of 'NOP'
E4B8 EX AF,AF'
E4B9 LD A,E Set a counter to (enable_count - clipped_width). We'll clip until this many bytes have been written
E4BA SUB C
svp_enable_cont E4BB EXX Bank
E4BC POP HL Restore enables pointer
E4BD LD C,A Move counter to C
E4BE EX AF,AF' Unbank the opcode we'll write
Set the addresses in the jump table to NOP or LD (HL),A.
svp_enables_iters E4BF LD B,$03 Set B for 3 iterations (self modified by $E4A9)
Start loop
svp_enables_loop E4C1 LD E,(HL) Fetch an address
E4C2 INC HL
E4C3 LD D,(HL)
E4C4 LD (DE),A Write a new opcode
E4C5 INC HL Advance
E4C6 LD E,(HL) Fetch an address
E4C7 INC HL
E4C8 LD D,(HL)
E4C9 INC HL Advance
E4CA LD (DE),A Write a new opcode
E4CB DEC C Count down the counter
E4CC JR NZ,setup_vischar_plotting_0 Jump if nonzero
E4CE XOR $77 Swap between LD (HL),A and NOP
setup_vischar_plotting_0 E4D0 DJNZ svp_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 the top of the screen.
E4D2 EXX Bank
E4D3 LD A,D Is top skip zero?
E4D4 AND A
E4D5 LD DE,$0000 Initialise our Y value to zero
E4D8 JR NZ,svp_y_skip_set Jump if top skip isn't zero
E4DA LD A,($81BC) Compute Y = map_position_y * 8 (pixels per column)
E4DD LD L,A
E4DE LD H,$00
E4E0 ADD HL,HL
E4E1 ADD HL,HL
E4E2 ADD HL,HL
E4E3 EX DE,HL Bank the temporary Y
E4E4 LD L,(IY+$1A) Fetch vischar.iso_pos.y
E4E7 LD H,(IY+$1B)
E4EA AND A Clear carry flag
E4EB SBC HL,DE Compute Y = (vischar.iso_pos.y - Y)
E4ED ADD HL,HL Multiply Y by 24 (columns)
E4EE ADD HL,HL
E4EF ADD HL,HL
E4F0 LD E,L
E4F1 LD D,H
E4F2 ADD HL,HL
E4F3 ADD HL,DE
E4F4 EX DE,HL Move Y into DE
svp_y_skip_set E4F5 LD A,($81B5) Compute x = iso_pos_x - map_position_x
E4F8 LD HL,$81BB
E4FB SUB (HL)
E4FC LD L,A Copy x to HL and sign extend it
E4FD LD H,$00
E4FF JR NC,svp_x_skip_set
E501 LD H,$FF
svp_x_skip_set E503 ADD HL,DE Combine the x and y values
E504 LD DE,$F290 Add the screen buffer start address
E507 ADD HL,DE
E508 LD ($81A2),HL Save the finalised screen buffer pointer
E50B LD HL,$8100 Point HL at the mask_buffer
E50E POP DE Retrieve the top skip and clipped height
E50F PUSH DE
E510 LD A,D mask buffer pointer += top_skip * 4
E511 ADD A,A
E512 ADD A,A
E513 ADD A,L
E514 LD L,A
E515 LD A,(IY+$1A) mask buffer pointer += (vischar.iso_pos.y & 7) * 4
E518 AND $07
E51A ADD A,A
E51B ADD A,A
E51C ADD A,L
E51D LD L,A
E51E LD ($81B0),HL Set foreground_mask_pointer
E521 POP DE Retrieve the top skip and clipped height
E522 LD A,D Is top skip zero?
E523 AND A
E524 JR Z,setup_vischar_plotting_1 Jump if so
Generic multiply loop.
E526 LD D,A Copy top_skip to loop counter
E527 XOR A Zero the accumulator
E528 LD E,(IY+$1E) Set multiplier to (vischar.width_bytes - 1)
E52B DEC E
Start loop
svp_mult_loop E52C ADD A,E Accumulate
E52D DEC D Decrement counter
E52E JP NZ,svp_mult_loop ...loop
D will be set to zero here either way: if the loop terminates, or if jumped into.
setup_vischar_plotting_1 E531 LD E,A Set DE to skip (result)
E532 LD HL,($81AC) Advance bitmap_pointer by 'skip'
E535 ADD HL,DE
E536 LD ($81AC),HL
E539 LD HL,($81AE) Advance mask_pointer by 'skip'
E53C ADD HL,DE
E53D LD ($81AE),HL
It's unclear as to why this value is preserved since it's not used by the caller.
E540 POP BC Restore the lefthand skip and clipped width
The Z flag remains set from E52E signalling "is visible".
E541 RET Return
Prev: E40F Up: Map Next: E542