I noticed that there are several parts of the JSW code which effectively replicate the same function - namely using the table in page #82 of the code to point HL at the appropriate address for drawing various moving entities onto the pixel display and/or pixel buffer.
So I have rewritten several parts of the code to allow a shared routine to be CALLed (with various entry points) which handles the table at page #82, and saves quite a few bytes (I would estimate about 30-40, all told) in the process:
Entry point from ‘Draw Arrows’/’Draw Guardians’ (Input: B = pixel y-coordinate, C = byte containing x-coordinate):
LD A, B
LD D, A
LD A, C
Entry point from ‘Draw Willy’ (Input: B = pixel y-coordinate, A = byte containing x-coordinate):
LD C, A
LD L, B
Entry point for Foot on ‘Game Over’ Screen (Input L = y-coordinate, C = #0F):
LD H, #82
LD A, (HL)
LD H, (HL)
LD L, A
; HL now points at pixel-buffer coordinates (#6xxx); for guardians and arrows, D also points at high byte of attribute-buffer coordinates.
Further code changes to facilitate the above:
In ‘Game Over’, replace the code at #8C71-#8C7F with LD L, A followed by LD C, #0F, then a CALL to the appropriate entry point above and finally a RES 5, H command (adjustment made in order to draw to addresses #4xxx instead of #6xxx).
In ‘Draw Arrows’, the CALL to the above makes the existing commands at #926A-#9277 and #928A-#928C redundant. The command at #9267 needs to be adjusted to write the arrow y-coordinate to B instead of E, that is then followed by a command to write the arrow x-coordinate to C; then CALL the above; after the CALL have LD E, L; finally, the references to HL at #927C, #9286 and #9289 should be replaced with DE.
In ‘Draw Guardians’, #91D6 writes guardian y-coordinate to B instead of E, follow that with a command which writes guardian byte 02 to C; CALL the above; after the CALL have a PUSH HL then LD H, D; after that, NOP out everything up to (but not including) #91EB; and replace #9220-#922D with POP HL.
[The next two steps rely on the ‘Draw a Sprite’ routine at #9456 having been subject to an earlier rewrite of mine, so that it draws the room’s whole complement of guardians (or Maria), and reacts to any collision after RETurning back to the main guardian-drawing routine.]
In ‘Draw Willy’, after the existing code up to and including #963A, the A register holds Willy's y-coordinate; after that insert LD B, A and LD A, (#85D3), then CALL the appropriate entry point above; #9660-#967F is then redundant; simply point DE at Willy's graphic (the appropriate animation frame, or the Flying Pig if necessary), then set LD C, #01 and JUMP to #9456.
In ‘Draw the Toilet’, replace #95B4-#95BA with LD C, #01 and LD HL, #68BC, then at #95BB change the destination of the CALL to #9456.
The only place where the original code employing the table at #8200 remains unchanged, and I have made no attempt to use the above 'shared subroutine' approach, is within the 'Draw a Rope' routine - I think it would be too complicated to unravel the segment-drawing loop (and it would probably not yield any byte-savings).