![]() |
Routines |
| Prev: B2C5 | Up: Map | Next: B37F |
|
Used by the routines at DRAW_OBJECT and CALC_2D_INFO.
The graphic (+0) indexes GRAPHICS for the sprite. A sprite whose first byte is 0 draws nothing: the routine then drops its own return address, so its RET leaves its caller too.
Sprites are turned in place, and the width byte remembers which way round the data now is: bit 7 set while it is stored upside down, bit 6 while mirrored. Bits 7 and 6 of the object's flags (+7) say how it wants to be drawn. Where they disagree the data is turned and the sprite's bit toggled, so an object that keeps facing one way costs nothing after the first time, while two objects sharing a sprite and facing opposite ways turn it back and forth every time each is drawn.
Upside down is done by swapping whole rows end for end; mirroring by reversing the order of each row's cells and the bits of every byte, through REVERSED. Knight Lore does the same in three routines; here they are one.
|
||||||||||||
| FIND_SPRITE | B2EE | LD L,(IX+$00) | DE = the sprite, from the graphic table | |||||||||
| B2F1 | LD H,$00 | |||||||||||
| B2F3 | ADD HL,HL | |||||||||||
| B2F4 | LD BC,GRAPHICS | |||||||||||
| B2F7 | ADD HL,BC | |||||||||||
| B2F8 | LD E,(HL) | |||||||||||
| B2F9 | INC HL | |||||||||||
| B2FA | LD D,(HL) | |||||||||||
| B2FB | LD A,(DE) | A real sprite | ||||||||||
| B2FC | AND A | |||||||||||
| B2FD | JR NZ,FIND_SPRITE_0 | |||||||||||
| B2FF | INC SP | None: return from the caller as well | ||||||||||
| B300 | INC SP | |||||||||||
| B301 | RET | |||||||||||
| FIND_SPRITE_0 | B302 | PUSH DE | Kept | |||||||||
| B303 | LD A,(DE) | The sprite's bit 7 against the object's: the same means no turning over | ||||||||||
| B304 | XOR (IX+$07) | |||||||||||
| B307 | AND $80 | |||||||||||
| B309 | JR Z,FIND_SPRITE_4 | |||||||||||
| B30B | LD A,(DE) | Toggle the sprite's bit | ||||||||||
| B30C | XOR $80 | |||||||||||
| B30E | LD (DE),A | |||||||||||
| B30F | RLCA | B = bytes a row: the width in bits 0 to 3, times two for the mask and image bytes | ||||||||||
| B310 | AND $1E | |||||||||||
| B312 | LD B,A | |||||||||||
| B313 | INC DE | C = the height in rows; DE on the data | ||||||||||
| B314 | LD A,(DE) | |||||||||||
| B315 | LD C,A | |||||||||||
| B316 | INC DE | |||||||||||
| B317 | PUSH BC | HL = B * C, the data's length, plus the start: one past the end | ||||||||||
| B318 | PUSH DE | |||||||||||
| B319 | LD E,C | |||||||||||
| B31A | LD D,$00 | |||||||||||
| B31C | LD H,D | |||||||||||
| B31D | LD L,D | |||||||||||
| FIND_SPRITE_1 | B31E | ADD HL,DE | ||||||||||
| B31F | DJNZ FIND_SPRITE_1 | |||||||||||
| B321 | POP DE | |||||||||||
| B322 | POP BC | |||||||||||
| B323 | ADD HL,DE | |||||||||||
| B324 | EX DE,HL | DE one past the end; HL one past the first row | ||||||||||
| B325 | LD A,B | |||||||||||
| B326 | CALL ADD_HL_A | |||||||||||
| B329 | DEC DE | DE on the last byte of the last row, HL on the last byte of the first | ||||||||||
| B32A | DEC HL | |||||||||||
| B32B | SRL C | Swap rows in pairs: half the height | ||||||||||
| FIND_SPRITE_2 | B32D | PUSH BC | Swap the two rows byte by byte, working backwards | |||||||||
| FIND_SPRITE_3 | B32E | LD A,(DE) | ||||||||||
| B32F | LD C,(HL) | |||||||||||
| B330 | LD (HL),A | |||||||||||
| B331 | LD A,C | |||||||||||
| B332 | LD (DE),A | |||||||||||
| B333 | DEC HL | |||||||||||
| B334 | DEC DE | |||||||||||
| B335 | DJNZ FIND_SPRITE_3 | |||||||||||
| B337 | POP BC | HL on to the end of the next row down; DE is already at the end of the row before its last | ||||||||||
| B338 | LD A,B | |||||||||||
| B339 | CALL ADD_HL_A | |||||||||||
| B33C | LD A,B | |||||||||||
| B33D | CALL ADD_HL_A | |||||||||||
| B340 | DEC C | The next pair | ||||||||||
| B341 | JR NZ,FIND_SPRITE_2 | |||||||||||
| FIND_SPRITE_4 | B343 | POP DE | The sprite's bit 6 against the object's | |||||||||
| B344 | PUSH DE | |||||||||||
| B345 | LD A,(DE) | |||||||||||
| B346 | XOR (IX+$07) | |||||||||||
| B349 | AND $40 | |||||||||||
| B34B | JR Z,FIND_SPRITE_7 | |||||||||||
| B34D | LD A,(DE) | Toggle the sprite's bit; B and C = the width in cells | ||||||||||
| B34E | XOR $40 | |||||||||||
| B350 | LD (DE),A | |||||||||||
| B351 | AND $0F | |||||||||||
| B353 | LD B,A | |||||||||||
| B354 | LD C,A | |||||||||||
| B355 | INC DE | The height into A' | ||||||||||
| B356 | LD A,(DE) | |||||||||||
| B357 | EX AF,AF' | |||||||||||
| B358 | INC DE | HL' reads and HL writes, both from the first row; B' = the page of the bit reversal table | ||||||||||
| B359 | EX DE,HL | |||||||||||
| B35A | PUSH HL | |||||||||||
| B35B | EXX | |||||||||||
| B35C | POP HL | |||||||||||
| B35D | LD B,$F1 | |||||||||||
| B35F | EXX | |||||||||||
| FIND_SPRITE_5 | B360 | EXX | Push a row's pairs, each byte reversed: E' the mask, D' the image | |||||||||
| B361 | LD C,(HL) | |||||||||||
| B362 | LD A,(BC) | |||||||||||
| B363 | LD E,A | |||||||||||
| B364 | INC HL | |||||||||||
| B365 | LD C,(HL) | |||||||||||
| B366 | LD A,(BC) | |||||||||||
| B367 | LD D,A | |||||||||||
| B368 | INC HL | |||||||||||
| B369 | PUSH DE | |||||||||||
| B36A | EXX | |||||||||||
| B36B | DJNZ FIND_SPRITE_5 | |||||||||||
| B36D | LD B,C | Pop them back over the row: last first, so the cells come back in the reverse order | ||||||||||
| FIND_SPRITE_6 | B36E | POP DE | ||||||||||
| B36F | LD (HL),E | |||||||||||
| B370 | INC HL | |||||||||||
| B371 | LD (HL),D | |||||||||||
| B372 | INC HL | |||||||||||
| B373 | DJNZ FIND_SPRITE_6 | |||||||||||
| B375 | EX AF,AF' | The next row, until the height runs out | ||||||||||
| B376 | DEC A | |||||||||||
| B377 | JR Z,FIND_SPRITE_7 | |||||||||||
| B379 | EX AF,AF' | |||||||||||
| B37A | LD B,C | |||||||||||
| B37B | JR FIND_SPRITE_5 | |||||||||||
| FIND_SPRITE_7 | B37D | POP DE | DE = the sprite | |||||||||
| B37E | RET | |||||||||||
| Prev: B2C5 | Up: Map | Next: B37F |