Routines |
Prev: E40F | Up: Map | Next: E542 |
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.
|
||||||||||||||
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 |