Prev: DD7E Up: Map Next: DE4C
DDA1: Draw/erase foreground scenery items
Used by the routine at D4FC.
These drawing/erasing routines are similar to the standard ones at DBF5, but because the foreground scenery occupies its own screen area and won't overlap other scenery, they're simplified slightly.
DDA1 LD A,$00 Flag indicating whether (any part of) graphic is visible on screen - set to 0 at start of graphics routine
DDA3 LD ($EAD5),A
DDA6 LD HL,($EACD) Graphic address pointer to foreground scenery graphics
DDA9 LD A,(HL) Byte indicating number of tiles within the graphic
DDAA INC HL
Tile drawing loop
DDAB LD ($EAD0),A Store graphic tile counter
DDAE LD C,(HL) Horizontal graphic offset (in pixels)
DDAF INC HL
DDB0 EX DE,HL Swap graphic address pointer into DE
Adjust graphic's screen position with horizontal offset:
DDB1 LD HL,($EAD3) Horizontal graphic position on screen in pixels
DDB4 LD A,C Get horizontal graphics pixel offset value
DDB5 RLA Rotate the bits left
DDB6 SBC A,A If this subtract creates a carry, it means the graphic offset is negative, otherwise positive
DDB7 LD B,A Store this value in B register (255 = negative, 0 = positive)
DDB8 ADD HL,BC Add (or subtract if negative) the offset from the horizontal graphics position
DDB9 EX DE,HL Swap into DE
DDBA LD A,D Get high byte of offset
DDBB CP $00
DDBD JP NZ,$DE45 If not zero it means the horizontal pixel position has gone over 255 and is therefore out of bounds. Jump out here and skip the rest of this tile.
Calculate the graphic's horizontal screen display address column position, and put into the E register:
DDC0 LD A,E The low byte (in the E register) contains the horizontal pixel position (including offset)
DDC1 RRA Get the graphic's screen character column by dividing the pixel value by 8
DDC2 RRA
DDC3 RRA
DDC4 AND $1F Filter out bits 5-7 (only values 0-31 needed)
DDC6 DEC A
DDC7 CP $1C Right-hand column screen border check
DDC9 JP NC,$DE45 No carry means character position is into the right border - jump out here
DDCC INC A Increment to return to place after the DEC a few instructions earlier
DDCD INC A The horizontal position is stored from column 1 (2nd screen column), whereas screen display address counts from column 0 as the first one, so adjust the horizontal character position by +1 so that it calculates correctly
DDCE LD E,A Store adjusted column position in E register
Check for vertical screen (scroll) boundary:
DDCF LD C,(HL) Get vertical graphic pixel offset value
DDD0 LD A,($EAD2) Graphic's vertical screen position
DDD3 ADD A,C Add the offset
DDD4 CP $70 Vertical pixel position 112 is the top of the scroll, out of bounds for drawing graphics
DDD6 JR NC,$DE45 No carry here means the object is in the scroll area at the bottom of the screen, and out of bounds for drawing - jump out here
Calculate high byte/vertical part of screen display address:
DDD8 ADD A,$10 The vertical graphic position is stored from the top of the playing area, but the screen display is calculated from the very top of the screen. Therefore add 16 pixels to adjust for the decorative border offset at the top of the screen
DDDA LD D,A Store in high byte of screen display address
DDDB AND $07 Bits 0-2 indicate pixel number (0-7) in character row
DDDD LD C,A Put in C register for safe keeping
DDDE INC HL
DDDF LD A,$01 This is the flag indicating whether (any part of the graphic) is visible on-screen (0 = not visible, 1 = visible)
DDE1 LD ($EAD5),A It's set here to visible (1) as part of the item is visible
DDE4 LD A,D Get the graphic's adjusted vertical screen pixel position
DDE5 RLA Character row is currently indicated by bits 3-5 so shift them left twice to bits 5-7
DDE6 RLA
DDE7 AND $E0 Get those top three bits (filter out any others)...
DDE9 ADD A,E ...and combine them with bits 0-4 which hold the column number, to form the screen display address low byte
DDEA LD E,A
DDEB LD A,D Vertical pixel position, from top of screen display
DDEC RRA Divide by 8 to get screen display (character) row
DDED RRA
DDEE RRA
DDEF AND $18 Bits 3 (8) and 4 (16) include the screen display address high byte character row (0-24)
DDF1 ADD A,$40 Set bit 6 (always set for screen addresses)
DDF3 ADD A,C C contains the pixel row number in the character line (0-7). Add this to the high byte of the address
DDF4 LD D,A Put the calculated screen address high byte into the D register
DDF5 LD B,(HL) Number of bytes in the graphic tile to print
DDF6 INC HL Advance address pointer to start of tile graphics
DDF7 EX DE,HL ...and swap into DE register
DDF8 LD A,($EACF) Check draw/erase flag
DDFB CP $01
DDFD JR Z,$DE1D If it's DRAW, jump out here....
ERASE graphic pixels on screen:
DDFF LD A,H Erase pixels within this character square - get pixel row in character square from screen display address
DE00 AND $07 Keep bits 0-2 so that A now contains the pixel row number in the character square
Erase pixel loop. Foreground scenery is out of the way of other room scenery/items so no need to use AND and OR to preserve existing pixels:
DE02 LD (HL),$00 Clear pixels in this on-screen byte
DE04 INC DE Move to next byte of graphic tile (mainly for count purposes)
DE05 INC A Increment the pixel row count/number
DE06 AND $07
DE08 JR Z,$DE0D If zero we've got to pixel row 8, so jump out here to re-calculate screen display address for the next pixel row
DE0A INC H ...Otherwise move down one pixel line
DE0B JR $DE19 ...And continue clearing the square
Re-calculate screen display address with new pixel row:
DE0D LD A,H Reset pixel row (bits 0-2 in high byte of the screen display address)
DE0E AND $F8
DE10 LD H,A
DE11 LD A,L Increment column by 32 to move down to next screen row
DE12 ADD A,$20
DE14 JR C,$DE37 Crossing a 1/3 screen boundary? ...If so, jump out of routine here
DE16 LD L,A Otherwise, store the amended screen display address low byte
DE17 LD A,$00 ...reset the pixel counter to 0...
DE19 DJNZ $DE02 ...and draw the rest of the bytes in the tile
DE1B JR $DE3B When finished, go and check if there are more tiles to draw
DRAW graphic pixels on screen:
DE1D LD A,(DE) Get graphics byte
DE1E LD (HL),A Draw on screen
DE1F INC DE Move to next byte of the graphics tile
DE20 LD A,H Increment and check the pixel row (bits 0-2 of screen display address high byte)
DE21 INC A
DE22 AND $07
DE24 JR Z,$DE29 If zero we've got to pixel row 8, so jump out here to re-calculate screen display address for the next pixel row
DE26 INC H ...Otherwise, move down one pixel line
DE27 JR $DE33 ...And continue clearing the square
Re-calculate screen display address with new pixel row:
DE29 LD A,H Reset pixel row (bits 0-2 in high byte of the screen display address)
DE2A AND $F8
DE2C LD H,A
DE2D LD A,L Increment column by 32 to move down to next screen row
DE2E ADD A,$20
DE30 JR C,$DE37 Crossing a 1/3 screen boundary? ...If so, jump out of routine here
DE32 LD L,A Otherwise, store the amended screen display address low byte
DE33 DJNZ $DE1D ...and continue to draw the rest of the tile graphic
DE35 JR $DE3B When finished, go and check if there are more tiles to draw
ERASE or DRAW screen display address has moved into the next third of the screen.
As this will be the bottom third of the screen where the scroll is, there's no need to calculate anything - there's nothing more to erase/draw.
DE37 DEC DE DE was prematurely incremented in the loops at DE04 or DE1F so if this was done, revert this change
DE38 INC DE Then increment it by the remaining tile bytes, to get to the start of the next tile
DE39 DJNZ $DE38
Tile finished - check for next tile:
DE3B EX DE,HL Swap the screen display address and graphics address pointers
DE3C LD A,($EAD0) Get the graphic tile counter
DE3F DEC A Reduce by one
DE40 JP NZ,$DDAB If there are still tiles to draw, go and draw them
DE43 JR $DE4B Jump to RET at the end of this routine
Jump here if screen position to draw/erase to is in right screen border (from DDC9) or into the scroll at the bottom third of the screen (from DDD6)
Nothing to draw/erase for the rest of this tile, so can skip past it
DE45 INC HL Move pointer to the address holding the number of graphic bytes in this tile
DE46 LD B,(HL) Get the byte counter
DE47 INC HL Advance to the start of the tile's graphic bytes
DE48 EX DE,HL Swap back into DE register pair
DE49 JR $DE38 Jump to the routine that skips the rest of the bytes
Jump here once all of the tiles have been drawn/erased
DE4B RET
Prev: DD7E Up: Map Next: DE4C