Prev: B3B6 Up: Map Next: B44F
B3D3: Draw Object
Used by the routine at ResolveObjectOrder.
Draws the sprite of an object into the buffer, using whatever of the room has already been drawn as the background. An object of type 01 is only a marker that something has to be erased, so it is removed instead of being drawn.
The sprite data is for whole bytes. If the screen x co-ordinate of the object is not a multiple of eight, the sprite is shifted to the right by the difference as it is drawn, which makes it one byte wider. Sprites are at most five bytes wide.
The drawing is done by two pieces of code that are set up for the width of the sprite. Each is made of a run of identical units, one for each byte column, and a jump into the run, which is patched with a displacement, starts it at the first unit that is needed. The stack pointer is made to point at the sprite data, so that each pair of bytes can be fetched with a POP.
Each pair is a mask byte followed by a pixel byte. The bits of the buffer that are under the mask are cleared and then the pixel byte is merged in.
Input
IX Object record
An object of type 01 only marks an area to be erased, so it is freed and not drawn.
DrawObject B3D3 LD A,(IX+$00) Jump to DrawObject_Project if the type of the object is not 01.
B3D6 CP $01
B3D8 JR NZ,DrawObject_Project
B3DA LD (IX+$00),$00 Set the type of the object to 00, which frees it.
B3DE RET Return.
Work out where on the screen the sprite goes and fetch the sprite, flipped to the right way round.
DrawObject_Project B3DF RES 4,(IX+$07) Clear the flag that says the object needs drawing.
B3E3 CALL CalculatePixelCoordinates Call CalculatePixelCoordinates to work out the screen position of the object.
B3E6 RET NC Return if the object is above the top of the screen.
This entry point is used by the routines at DisplayObjectsCarried, PrintTableSprite, PrintSprites and DrawLives.
DrawObject_Sprite B3E7 CALL GetSpriteAddress Call GetSpriteAddress to flip the sprite if needed and get its address in DE.
Set up the drawing code for a sprite that has to be shifted.
B3EA LD A,(IX+$1A) Fetch the screen x co-ordinate of the object.
B3ED AND %00000111 Keep the number of bits to shift by.
B3EF JR Z,DrawObject_Aligned Jump to DrawObject_Aligned if there is no shift.
B3F1 RLCA Double it.
B3F2 AND %00001110 Keep the number as an even number of pages.
B3F4 OR %11110000 Add the page of the first shift table, F0.
B3F6 LD H,A Set H to the page of the table for this shift.
The sprite is a byte wider when it is shifted. Set that width in the object.
B3F7 LD A,(DE) Fetch the first byte of the sprite, which holds its width, and move on to the height.
B3F8 INC DE
B3F9 AND %00000111 Keep only the width.
B3FB INC A Add one for the extra byte.
B3FC LD B,A Stash the width in B.
B3FD LD (IX+$18),A Write it to the object.
Work out the displacement that jumps into the shifted code at the first unit that is needed. A unit is 10 bytes long, and the last of them ends at B4CD.
B400 DEC A Subtract one to get the width of the sprite.
B401 AND %00000111 Keep the width (which is at most five).
B403 ADD A,A Multiply it by sixteen, the size of a unit.
B404 ADD A,A
B405 ADD A,A
B406 ADD A,A
B407 NEG Negate it.
B409 ADD A,$50 Add 50, the distance from the displacement to the end of the units.
DrawObject_SetOffset B40B LD ($B47C),A Write it into the jump that starts the drawing, at B47C.
Work out the amount to add to the buffer address to get from the end of a row of the sprite to the start of the next.
B40E LD A,B Fetch the width, and invert it.
B40F CPL
B410 ADD A,$22 Add 22, which makes the amount 21 less the width.
B412 LD ($B4D0),A Write it to the code that finishes a row, at B4D0.
Fetch the height of the sprite, and cut it down if the sprite sticks out above the top of the screen.
B415 LD A,(DE) Fetch the height and move on to the data.
B416 INC DE
B417 LD (IX+$19),A Write the height to the object.
B41A ADD A,(IX+$1B) Add the bottom of the sprite to get the top of the sprite.
B41D SUB $C0 Subtract C0 to see how far it sticks out of the screen.
B41F JR C,DrawObject_SetAddress Jump to DrawObject_SetAddress if it does not.
B421 NEG Negate the amount.
B423 ADD A,(IX+$19) Subtract it from the height, and write that to the object.
B426 LD (IX+$19),A
Find where in the buffer the sprite starts and set the stack pointer to the data.
DrawObject_SetAddress B429 LD C,(IX+$1A) Set BC to the pixel co-ordinates of the sprite.
B42C LD B,(IX+$1B)
B42F CALL CalculateBufferAddress Call CalculateBufferAddress to get the address in the buffer in BC.
B432 LD ($A717),SP Save the stack pointer in SavedStackPointer.
B436 EX DE,HL Point the stack pointer at the sprite data.
B437 LD SP,HL
B438 EX DE,HL
B439 LD A,(IX+$19) Fetch the number of rows to draw.
B43C JR DrawLines Jump to DrawLines to start drawing.
Set up the drawing code for a sprite that is not shifted. Each unit of it is 08 bytes long, and the last of them ends at DrawLines_FinishRow.
DrawObject_Aligned B43E LD A,(DE) Fetch the first byte of the sprite, which holds its width, and move on to the height.
B43F INC DE
B440 AND %00001111 Keep only the width.
B442 LD (IX+$18),A Write the width to the object.
B445 LD B,A Stash the width in B.
B446 ADD A,A Multiply it by eight, the size of a unit.
B447 ADD A,A
B448 ADD A,A
B449 NEG Negate it.
B44B SUB $06 Subtract 06, which makes the jump end at the last unit.
B44D JR DrawObject_SetOffset Jump to DrawObject_SetOffset to write the displacement and carry on.
View the equivalent code in;
Prev: B3B6 Up: Map Next: B44F