Prev: E29F Up: Map Next: E3FA
E2A2: Plot masked sprite (16px)
This is a plotter for 16 pixel-wide masked sprites. This is used for characters and objects.
Input
IY Pointer to visible character.
Mask off the bottom three bits of the vischar's (isometric projected) x position and treat it as a signed field. This tells us how far we need to shift the sprite left or right. -4..-1 => left shift by 4..1px; 0..3 => right shift by 0..3px.
plot_masked_sprite_16px E2A2 LD A,(IY+$18) x = (vischar.iso_pos.x & 7)
E2A5 AND $07
E2A7 CP $04 Is x equal to 4 or above? (-4..-1)
E2A9 JP NC,pms16_left Jump if so
Right shifting case.
A is 0..3 here: the amount by which we want to shift the sprite right. The following op turns that into a jump table distance. e.g. It turns (0,1,2,3) into (3,2,1,0) then scales it by the length of each rotate sequence (6 bytes) to obtain the jump offset.
pms16_right E2AC CPL x = (~x & 3)
E2AD AND $03
E2AF ADD A,A Multiply by six to get the jump distance
E2B0 LD H,A
E2B1 ADD A,A
E2B2 ADD A,H
E2B3 LD ($E2DC),A Self modify the JR at pms16_right_mask_jump to jump into the mask rotate sequence
E2B6 LD ($E2F4),A Self modify the JR at pms16_right_bitmap_jump to jump into the bitmap rotate sequence
E2B9 EXX Fetch mask_pointer
E2BA LD HL,($81AE)
E2BD EXX Fetch bitmap_pointer
E2BE LD HL,($81AC)
pms16_right_height_iters E2C1 LD B,$20 Set B for 32 iterations (self modified by DC73)
Start loop
pms16_right_loop E2C3 LD D,(HL) Load the bitmap bytes bm0,bm1 into D,E
E2C4 INC HL
E2C5 LD E,(HL)
E2C6 INC HL
E2C7 PUSH HL Preserve the bitmap pointer
E2C8 EXX Bank
E2C9 LD D,(HL) Load the mask bytes mask0,mask1 into D',E'
E2CA INC HL
E2CB LD E,(HL)
E2CC INC HL
E2CD PUSH HL Preserve the mask pointer
E2CE LD A,($81B7) Is the top bit of flip_sprite set?
E2D1 AND A
E2D2 CALL M,flip_16_masked_pixels Call flip_16_masked_pixels if so
E2D5 LD HL,($81B0) Fetch foreground_mask_pointer
Shift the mask.
Note: The 24px version does bitmap rotates then mask rotates. Is this the opposite way around to save a bank switch?
E2D8 LD C,$FF mask2 = $FF
E2DA SCF carry = 1
pms16_right_mask_jump E2DB JR pms16_right_mask_jumptable_0 Jump into shifter (self modified by E2B3)
Rotate the mask bytes (D,E,C) right by one pixel.
pms16_right_mask_jumptable_0 E2DD RR D new_carry = mask0 & 1; mask0 = (mask0 >> 1) | (carry << 7); carry = new_carry
E2DF RR E new_carry = mask1 & 1; mask1 = (mask1 >> 1) | (carry << 7); carry = new_carry
E2E1 RR C new_carry = mask2 & 1; mask2 = (mask2 >> 1) | (carry << 7); carry = new_carry
pms16_right_mask_jumptable_1 E2E3 RR D Do the same again
E2E5 RR E
E2E7 RR C
pms16_right_mask_jumptable_2 E2E9 RR D Do the same again
E2EB RR E
E2ED RR C
Shift the bitmap.
Our 16px bitmap has two bitmap bytes to shift (D,E) but we'll need an extra byte to capture the shift-out (C).
pms16_right_mask_jumptable_end E2EF EXX Swap to bitmaps bank
E2F0 LD C,$00 bm2 = 0
E2F2 AND A (Suspect this is a stray instruction)
pms16_right_bitmap_jump E2F3 JR pms16_right_bitmap_jumptable_0 Jump into shifter (self modified by E2B6)
Rotate the bitmap bytes (D,E,C) right by one pixel.
Shift out the leftmost byte's bottom pixel into the carry flag.
pms16_right_bitmap_jumptable_0 E2F5 SRL D carry = bm0 & 1; bm0 >>= 1
Shift out the next byte's bottom pixel into the carry flag while shifting in the previous carry at the top. (x2)
E2F7 RR E new_carry = bm1 & 1; bm1 = (bm1 >> 1) | (carry << 7); carry = new_carry
E2F9 RR C new_carry = bm2 & 1; bm2 = (bm2 >> 1) | (carry << 7); carry = new_carry
pms16_right_bitmap_jumptable_1 E2FB SRL D Do the same again
E2FD RR E
E2FF RR C
pms16_right_bitmap_jumptable_2 E301 SRL D Do the same again
E303 RR E
E305 RR C
pms16_right_bitmap_jumptable_end E307 LD HL,($81A2) Load screen buffer pointer
E30A EXX Swap to bitmaps bank
Plot, using the foreground mask. See pms24_right_plot_0 for a discussion of this masking operation.
pms16_right_plot_0 E30B LD A,(HL) Load a foreground mask byte
E30C CPL Invert it
E30D OR D OR with mask byte mask0
E30E EXX Swap to bank containing bitmap bytes (in D & E) and screen buffer pointer (in HL)
E30F AND (HL) AND combined masks with screen byte
E310 EX AF,AF' Bank left hand term
E311 LD A,D Get bitmap byte bm0
E312 EXX Swap to bank containing mask bytes (in D' & E') and foreground mask pointer (in HL')
E313 AND (HL) AND with foreground mask byte
E314 LD D,A Save right hand term
E315 EX AF,AF' Unbank left hand term
E316 OR D Combine terms
E317 INC L Advance foreground mask pointer
E318 EXX Swap to bitmaps bank
pms16_right_plot_enable_0 E319 LD (HL),A Write pixel (self modified)
E31A INC HL Advance to next output pixel
E31B EXX Swap to masks bank
pms16_right_plot_1 E31C LD A,(HL) Do the same again for mask1 & bm1
E31D CPL
E31E OR E
E31F EXX
E320 AND (HL)
E321 EX AF,AF'
E322 LD A,E
E323 EXX
E324 AND (HL)
E325 LD E,A
E326 EX AF,AF'
E327 OR E
E328 INC L
E329 EXX
pms16_right_plot_enable_1 E32A LD (HL),A
E32B INC HL
E32C EXX
pms16_right_plot_2 E32D LD A,(HL) Do the same again for mask2 & bm2
E32E CPL
E32F OR C
E330 EXX
E331 AND (HL)
E332 EX AF,AF'
E333 LD A,C
E334 EXX
E335 AND (HL)
E336 LD C,A
E337 EX AF,AF'
E338 OR C
E339 INC L Advance foreground_mask_pointer by two (buffer is 4 bytes wide)
E33A INC L
E33B LD ($81B0),HL Save foreground_mask_pointer
E33E POP HL Restore the mask pointer
E33F EXX
pms16_right_plot_enable_2 E340 LD (HL),A
E341 LD DE,$0016 Advance screen buffer pointer by (24 - 2 = 22) bytes
E344 ADD HL,DE
E345 LD ($81A2),HL Save the screen buffer pointer
E348 POP HL Restore the bitmap pointer
E349 DEC B ...loop
E34A JP NZ,pms16_right_loop
E34D RET Return
Left shifting case.
A is 4..7 here, which we intepret as -4..-1: the amount by which we want to shift the sprite left.
pms16_left E34E SUB $04 4..7 => jump table offset 0..3
E350 ADD A,A Multiply by six to get the jump distance
E351 LD L,A
E352 ADD A,A
E353 ADD A,L
E354 LD ($E39A),A Self modify the JR at pms16_left_bitmap_jump to jump into the bitmap rotate sequence
E357 LD ($E37D),A Self modify the JR at pms16_left_mask_jump to jump into the mask rotate sequence
E35A EXX Fetch mask_pointer
E35B LD HL,($81AE)
E35E EXX Fetch bitmap_pointer
E35F LD HL,($81AC)
pms16_left_height_iters E362 LD B,$20 Set B for 32 iterations (self modified by E492)
Start loop
pms16_left_loop E364 LD D,(HL) Load the bitmap bytes bm1,bm2 into D,E
E365 INC HL
E366 LD E,(HL)
E367 INC HL
E368 PUSH HL Preserve the bitmap pointer
E369 EXX Bank
E36A LD D,(HL) Load the mask bytes mask1,mask2 into D',E'
E36B INC HL
E36C LD E,(HL)
E36D INC HL
E36E PUSH HL Preserve the mask pointer
E36F LD A,($81B7) Is the top bit of flip_sprite set?
E372 AND A
E373 CALL M,flip_16_masked_pixels Call flip_16_masked_pixels if so
E376 LD HL,($81B0) Fetch foreground_mask_pointer
Shift the mask.
E379 LD C,$FF mask0 = $FF
E37B SCF carry = 1
pms16_left_mask_jump E37C JR pms16_left_mask_jumptable_0 Jump into shifter (self modified by E357)
Rotate the mask bytes (C,D,E) left by one pixel.
pms16_left_mask_jumptable_0 E37E RL E new_carry = mask2 >> 7; mask2 = (mask2 << 1) | carry; carry = new_carry
E380 RL D new_carry = mask1 >> 7; mask1 = (mask1 << 1) | carry; carry = new_carry
E382 RL C new_carry = mask0 >> 7; mask0 = (mask0 << 1) | carry; carry = new_carry
pms16_left_mask_jumptable_1 E384 RL E Do the same again
E386 RL D
E388 RL C
pms16_left_mask_jumptable_2 E38A RL E Do the same again
E38C RL D
E38E RL C
pms16_left_mask_jumptable_3 E390 RL E Do the same again
E392 RL D
E394 RL C
Shift the bitmap.
pms16_left_mask_jumptable_end E396 EXX Swap to bitmaps bank
E397 XOR A bm0 = 0
E398 LD C,A
pms16_left_bitmap_jump E399 JR pms16_left_bitmap_jumptable_0 Jump into shifter (self modified by E354)
Rotate the bitmap bytes (C,D,E) left by one pixel.
pms16_left_bitmap_jumptable_0 E39B SLA E carry = bm2 >> 7; bm2 <<= 1
E39D RL D new_carry = bm1 >> 7; bm1 = (bm1 << 1) | (carry << 0); carry = new_carry
E39F RL C new_carry = bm0 >> 7; bm0 = (bm0 << 1) | (carry << 0); carry = new_carry
pms16_left_bitmap_jumptable_1 E3A1 SLA E Do the same again
E3A3 RL D
E3A5 RL C
pms16_left_bitmap_jumptable_2 E3A7 SLA E Do the same again
E3A9 RL D
E3AB RL C
pms16_left_bitmap_jumptable_3 E3AD SLA E Do the same again
E3AF RL D
E3B1 RL C
Plot, using foreground mask.
See pms24_right_plot_0 for a discussion of this masking operation.
pms16_left_bitmap_jumptable_end E3B3 LD HL,($81A2) Load screen buffer pointer
E3B6 EXX Swap to masks bank
pms16_left_plot_0 E3B7 LD A,(HL) Load a foreground mask byte
E3B8 CPL Invert it
E3B9 OR C OR with mask byte mask0
E3BA EXX Swap to bank containing bitmap bytes (in D & E) and screen buffer pointer (in HL)
E3BB AND (HL) AND combined masks with screen byte
E3BC EX AF,AF' Bank left hand term
E3BD LD A,C Get bitmap byte bm0
E3BE EXX Swap to bank containing mask bytes (in D' & E') and foreground mask pointer (in HL')
E3BF AND (HL) AND with foreground mask byte
E3C0 LD C,A Save right hand term
E3C1 EX AF,AF' Unbank left hand term
E3C2 OR C Combine terms
E3C3 INC L Advance foreground mask pointer
E3C4 EXX Swap to bitmaps bank
pms16_left_plot_enable_0 E3C5 LD (HL),A Write pixel (self modified)
E3C6 INC HL Advance to next output pixel
E3C7 EXX Swap to masks bank
pms16_left_plot_1 E3C8 LD A,(HL) Do the same again for mask1 & bm1
E3C9 CPL
E3CA OR D
E3CB EXX
E3CC AND (HL)
E3CD EX AF,AF'
E3CE LD A,D
E3CF EXX
E3D0 AND (HL)
E3D1 LD D,A
E3D2 EX AF,AF'
E3D3 OR D
E3D4 INC L
E3D5 EXX
pms16_left_plot_enable_1 E3D6 LD (HL),A
E3D7 INC HL
E3D8 EXX
pms16_left_plot_2 E3D9 LD A,(HL) Do the same again for mask2 & bm2
E3DA CPL
E3DB OR E
E3DC EXX
E3DD AND (HL)
E3DE EX AF,AF'
E3DF LD A,E
E3E0 EXX
E3E1 AND (HL)
E3E2 LD E,A
E3E3 EX AF,AF'
E3E4 OR E
E3E5 INC L Advance foreground_mask_pointer by two (buffer is 4 bytes wide)
E3E6 INC L
E3E7 LD ($81B0),HL Save foreground_mask_pointer
E3EA POP HL Restore the mask pointer
E3EB EXX
pms16_left_plot_enable_2 E3EC LD (HL),A
E3ED LD DE,$0016 Advance screen buffer pointer by (24 - 2 = 22) bytes
E3F0 ADD HL,DE
E3F1 LD ($81A2),HL Save the screen buffer pointer
E3F4 POP HL Restore the bitmap pointer
E3F5 DEC B ...loop
E3F6 JP NZ,pms16_left_loop
E3F9 RET Return
Prev: E29F Up: Map Next: E3FA