jetsetdanny Posted October 19, 2025 Report Share Posted October 19, 2025 The Invisible Man is JSW hacked by Lee Prince in 2002 so that that you play as an invisible sprite and guardians cannot therefore collide with you (but precision jumps are very difficult). It was an entry in the comp.sys.sinclair Crap Games Competition 2002. The game has a custom BASIC loader and loading screen, and a modified title screen and scrolling message. The rooms are unmodified. The game is impossible to complete due to the same bugs which make the original JSW incompletable. The official Software Projects POKEs take care of that, so it's not a problem. I would like to record an RZX walkthrough of the game and make a video of it to be placed on the JSW Central YouTube channel. I've started the recording and got as far as "The Beach". However, I've come across a problem I don't seem to be able to solve satisfactorily. Apparently - that's a general remark, concerning all games - Willy has to have some pixels in order to be able to land on a rope. If all frames of Willy's sprite are pixelless - as is the case in The Invisible Man - Willy cannot get hold of a rope, he goes right through it. Hence, rooms where Willy has to use the rope are impossible to complete/pass through. I've had a look at SkoolKid's disassembly and as far as I can tell, the check in the code to see if Willy has landed on the rope is at #92C6 - #92D5: I *think* that the problem must be that the code checks if a given segment of the rope is touching anything else that's been drawn so far, e.g. Willy, but since Willy hasn't been "drawn" (because he has no pixels), the check is negative and so the signal that Willy is on the rope is not set as it should. Please correct me if this explanation is inaccurate. Now the question is: would anyone be able to suggest how to modify the original code so that Willy, while remaining invisible, would be able to get hold of the ropes as usual? Jet Set Willie and UncleWan 2 Quote Link to comment Share on other sites More sharing options...
Norman Sword Posted October 20, 2025 Report Share Posted October 20, 2025 (edited) Because this would always be attributed to the original person. I have no incentive to add code to what (as far as I can see) is a simple deletion of the willy definition. So in the words used on Dragons den "I'm out" ------------------------------- path that could be taken - just not by me 1) To collide with the rope, Willy needs a definition. The deletion of Willies definition, means that path is out. 2) If the definition is intact modify the code that draws willy - instead of actually putting the pixels to the screen- instead save the draw definition and the draw position, and return in the rope draw routine - add a routine to use Willies draw definition and Willies draw position to xor Willy to the screen Draw the rope - using xor - Willy will be flagged as collided in the normal way - movement on rope etc will still occur. on rope exit add a routine to use Willies definition and Willies draw position to xor Willy off the screen. The xor routine is a very simple sprite draw routine. Which would need adding, The above allows Willy to interact with the rope.... The original modification was simply deleting Willies definition. This is adding ten times the effort of the original person to try and fix his hack. Addendum:- Just looked at this again - every reference to drawing willy elsewhere .. e.g the dancing Willies/ death screen etc. would need deleting. Edited October 20, 2025 by Norman Sword jetsetdanny and Jet Set Willie 2 Quote Link to comment Share on other sites More sharing options...
jetsetdanny Posted October 20, 2025 Author Report Share Posted October 20, 2025 Thank you for taking the time to reply, Norman Sword! 👍 My current coding skills unfortunately aren't enough to write the code you've mentioned (simple as it may be). I did give the issue some more thought, though, and came up with a suggestion for an alternative solution that apparently doesn't work, but I will present it here because I don't understand some of the results of what I've tried to do and would be happy to have some answers. So I thought of the following solution looking at this part of the Main Loop: I thought that after everything that needs to be done with Willy is done (Willy is moved, the items that he is touching are collected), the Screen buffer (room + Willy + entities + items) at #6000 gets copied to the display file at #89F5. My idea was to, at this point, draw Willy to the #6000 Screen buffer again - before the buffer is copied to the display file - but this time using an empty sprite of Willy's. At #89F5, I inserted a call to #9700 where I copied the code from #95C8 ("Check and set the attribute bytes for Willy's sprite in the buffer at 5C00") and the code from #9637 ("Draw Willy to the screen buffer at 6000"), but (at #9772 and #977B in case of "The Nigthmare Room") pointing to an empty sprite instead of Willy's regular sprite. My idea was to erase Willy from the #6000 Screen buffer (by printing him again, but this time using an empty, pixelless sprite) right before the buffer was copied to the display file. The result is that my additional code prints Willy (or whatever sprite I point the instruction to) once again on top of the already printed Willy. It doesn't erase the already printed Willy, it ads pixels on top of him, so to speak, preserving the filled pixels that are already in place. Attached below are three experimental files that illustrate it, called TTMWI (trying to make Willy invisible). In the file "TTMWI (empty)" my additional code at #9700 prints an empty sprite. This results in the game looking normal (as if nothing has changed), because an empty (pixelless) sprite is printed on top of the regular Willy, so all you see is the regular Willy. In the file "TTMWI (bird)" my additional code prints the bird sprite from #BD00. What you see is a mixture of the regular Willy and the (backwards walking) bird, or, in "The Nightmare Room", of the flying pig and the bird (the latter is quite cool, actually). In the file "TTMWI (inverted)" my additional code prints a sprite from #9F00 where I placed an inverted set of Willy's sprites. The result is a solid white block, which demonstrates clearly that the code prints the original Willy's sprite and, on top of it (without erasing it though) an additional sprite selected by my additional code. What I don't understand is why the original Willy's sprite doesn't get erased - why its filled pixels stay in place instead of being wiped out by the empty pixels of the second sprite that is printed by my additional code. An answer to this enigma would be appreciated, as well as an opinion on whether this approach to making Willy invisible could work and, if so, what should be changed in my code to make it work 🙂 . TTMWI (inverted).tap TTMWI (bird).tap TTMWI (empty).tap Quote Link to comment Share on other sites More sharing options...
Norman Sword Posted October 20, 2025 Report Share Posted October 20, 2025 (edited) because the sprite print routine adds pixels - it never erases pixels - similar to 1+4=5 or 1+3+2=6. The result never gets less no matter how many positive numbers you add.Although technically the print routine gives the result as (1 or 4 =5) and (1 or 3 or 2=3) NOTE - the routine I mentioned uses XOR - and any number xor'd with itself is always 0. So how difficult is the xor version of the sprite print routine. Original hacked to xor - call once to draw and once to erase. sprite_xor ld b,#10 loop_xor: ld a,(de) xor (hl) ld (hl),a inc L inc de ld a,(de) xor (hl) ld (hl),a dec L inc de Inc h ld a,h and #07 jr nz,legal_val ld a,h sub 8 ld h,a ld a,L add a,#20 ld L,a legal_val: djnz loop_xor ret Edited October 20, 2025 by Norman Sword pet hate lower case "l" in code.. changing to "L" Spider and jetsetdanny 1 1 Quote Link to comment Share on other sites More sharing options...
Jet Set Willie Posted October 21, 2025 Report Share Posted October 21, 2025 Thank you, Norman! 🙂 I had just a very faint idea what I couldn´t think any further because of my lacking understanding, you wrote it perfectly down in your first answer! 🙂 Thank you! jetsetdanny 1 Quote Link to comment Share on other sites More sharing options...
jetsetdanny Posted October 22, 2025 Author Report Share Posted October 22, 2025 Thank you for the code, Norman Sword! I will work on applying it to an actual game file when time permits, hopefully soon. Quote Link to comment Share on other sites More sharing options...
Norman Sword Posted October 22, 2025 Report Share Posted October 22, 2025 (edited) Just checked the code - was aware it seemed different from what I normally do - e.g. was part modifying someone elses code. I can see the layout does not adjust for the screen 1/3rds correctly. so here, is how I do it as opposed to modifying someone else's code --- Too much time doing this. sprite_xor ld b,#10 loop_xor: ld a,(de) xor (hl) ld (hl),a inc L inc de ld a,(de) xor (hl) ld (hl),a dec L inc de inc h ld a,h and 7 jr nz,legal_val ld a,L add a,#20 ld L,a jr c,legal_val ld a,h sub 8 ld h,a legal_val: djnz loop_xor ret Addendum:- just to show what I said works --- 1) no idea what version of jsw I have used - so no idea how many of the original bugs are present 2) deliberately not the same as the file you want to edit. 3) comes equiped with spray paint - Pause to show where willy is 4) due to the pause addition.... Can play by pressing pause to see where willy is and movement keys .eg hold "gh" and play as normal. Willy is treated as still invisible in the game code. Addendum 2:- with a ghostbuster's radar - we track the invisible man. And that concludes my effort. INVISIBLE.tap INVISIBLE_Tracking.tap Edited October 22, 2025 by Norman Sword responding to theft of typed letters. I'll catch you one day Mr keyboard Jet Set Willie, jetsetdanny, Spider and 1 other 2 2 Quote Link to comment Share on other sites More sharing options...
Jet Set Willie Posted October 23, 2025 Report Share Posted October 23, 2025 21 hours ago, Norman Sword said: Addendum 2:- with a ghostbuster's radar - we track the invisible man. As this is a Willy case, I think it´s enough to put the corks back on the wine bottles, to keep the spirits in the bottles. 🤭 Quote Link to comment Share on other sites More sharing options...
Norman Sword Posted October 23, 2025 Report Share Posted October 23, 2025 (edited) And to take all the work out of modification... The data needed is in my "INVISIBLE TAP" file This is the minimum change needed to interact with willy - NOTE this omits the other changes I added ; to get this data look at these addresses in "INVISIBLE.TAP"- ; modification at start of rope draw - draw Willy to screen at #92a4 call willy_draw_on (3 BYTES) nop (1 BYTE) old LD IY,ytable (4 BYTES) ; with xor ??? if willy is present then no change here - leave to indicate looked at and aware of check at #92c9 and (hl) old (no change - read comment) AND (HL) ; the rope pixel changes from {or} to {xor} at #9311 xor (hl) (1 BYTE) old OR (HL) (1 BYTE) ; the final rope mode modification - get rid of Willy at #935e call willy_draw_off (3 BYTES) old LD A,(rope_status) (3 BYTES) ; Original Willy draw - now just saves data positions at #9660 jp save_willy (3 BYTES) old --- note 3 bytes which is the first instruction plus 1 byte from the next LD B,#10 (2 BYTES) LD A,(willy_att) (3 BYTES- ONLY FIRST BYTE NEEDS TO BE CHANGED) ; the code that is being called - org #9f00 screen_pos dw 0 screen_def dw 0 save_willy: ld a,(willy_att) and #1f or (ix+0) ; the x position ld L,a ld h,(ix+1) ld (screen_pos),HL ld (screen_def),de ret willy_pause: ld hl,(screen_pos) ; shift from #60 to #40 res 5,h call willy_xor1 LD DE,#0000 ret willy_draw_on: call willy_xor LD IY,ytable ret willy_draw_off call willy_xor LD A,(rope_status) ret willy_xor: ld hl,(screen_pos) willy_xor1: ld de,(screen_def) draw_xor: ld b,#10 loop_xor: ld a,(de) xor (hl) ld (hl),a inc de inc L ld a,(de) xor (hl) ld (hl),a inc de dec L inc h ld a,h and 7 jr nz,legal_val ld a,L add a,#20 ld L,a jr c,legal_val ld a,h sub 8 ld h,a legal_val: djnz loop_xor ret --------------------- PLUS Stop dancing willy routine - delete call remove Willy on plinth in death routine - delete call ------------------------------- A lot of effort for something I am not doing --- Edited October 25, 2025 by Norman Sword MtM, Jet Set Willie and jetsetdanny 1 1 1 Quote Link to comment Share on other sites More sharing options...
jetsetdanny Posted October 24, 2025 Author Report Share Posted October 24, 2025 Thank you so much, Norman Sword! 👍 I would definitely like to record a variant of JSW with an invisible Willy. However, I'm not sure how to proceed now. Lee Prince's "The Invisible Man" is incompletable. You have provided the code that allows to achieve the idea that Lee came up with. With this, I'm tempted to try to fix Lee's version with your code and make it available to anyone who might be interested as "The Invisible Man" - Bugfixed Version, with all due credit given to you in the accompanying Readme file, on this variant's page on JSW Central, in the JSW Central YouTube video description and in any announcements I would make about it. Would you be OK with this solution? Jet Set Willie and UncleWan 2 Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.