Jump to content
Jet Set Willy & Manic Miner Community

A total rewrite of JSW in 48k using Matthews core code


Norman Sword

Recommended Posts

The problem I am having is the fact  that any code I look at, has a lot of changes. If I spot a problem I change the code, The code area around this modification has been modified to fix the rope bug and the    res 7,A     which was before the     LD A,L     was ignored..

 

The code that deals with the offset into the rope data is confined to this local area. No other part of the program uses the rope data.

 

Still, I will modify to include the res 7,a in the listing above. (because it should have been included)

 

And yet again change the data.

 

With all sets of data the rope animation was happy to use the data provided 

Link to comment
Share on other sites

Curious if the change would do as I expected. Short answer yes..

 

ROPE_TABLE
x8300 DEFB 6*2+0,6*2+0,6*2+0,6*2+0,6*2+0,6*2+0,6*2+0,6*2+0
x8308 DEFB 6*2+0,6*2+0,6*2+0,6*2+0,6*2+0,6*2+0,6*2+0,6*2+0
x8310 DEFB 6*2+0,6*2+0,6*2+0,6*2+0,6*2+0,6*2+0,6*2+0,6*2+0
x8318 DEFB 6*2+0,6*2+0,6*2+0,6*2+0,6*2+0,6*2+0,6*2+0,6*2+0
x8320 DEFB 6*2+1,6*2+1,6*2+1,6*2+1,6*2+1,6*2+1,6*2+1,6*2+1
x8328 DEFB 6*2+1,6*2+1,6*2+1,6*2+1,6*2+2,6*2+2,6*2+2,6*2+2
x8330 DEFB 4*2+2,6*2+2,6*2+2,4*2+2,6*2+2,4*2+2,6*2+2,4*2+2
x8338 DEFB 6*2+2,4*2+2,4*2+2,4*2+2,6*2+2,4*2+2,4*2+2,4*2+2
x8340 DEFB 4*2+2,4*2+2,4*2+1,4*2+2,4*2+2,4*2+1,4*2+1,4*2+2
x8348 DEFB 4*2+1,4*2+1,4*2+2,4*2+2,4*2+3,4*2+2,4*2+3,4*2+2
x8350 DEFB 4*2+3,4*2+3,4*2+3,4*2+3,4*2+3,4*2+3

 

X9316 ADD A,(IX+rope1)                    ;$01

From here

;remove the rope swing direction bit (bit 7)
res 7,a                                ; it helps to include the full modifications
ld l,a
ld H,High ROPE_TABLE     ; $83

; extract the data, 00001100b contains the Y-shift
ld a,(hl)                               ;grab data   hl=pointer to rope data

and 1100b
rrca                                      ;instant crash is this value is odd (no possibility with previous AND instruction)

; add Y-shift onto the Y-table offset
add  a,iyl
ld iyl,a

;extract the data, 00000011b contains the data for X-shift
ld a,(hl)
and $03                             ;$03=3=00000011B

;To here

X9327 JR Z,L9350            ;Jump if so
X9329 LD B,A                   ;B is the count for rotations of the drawing byte (the rope drawing data bit)

Edited by Norman Sword
Link to comment
Share on other sites

and 1100b

rrca                                      ;instant crash if this value is odd (no possibility with previous AND instruction)

 

I don't think a crash will happen, because the value of A won't ever be odd if you've applied an AND #0C which resets Bits 0 and 1, and then only applied one RRCA command.  :)

 

I'm still not sure that the changes will fit into the original routine without further code-shifting, I think it's still too long by two bytes.  (The two instructions ADD A,IYL and LD IYL,A each require a 'FD' shift-opcode; perhaps that is where the discrepancy lies?)

 

However, Matthew usefully left a redundant two-byte instruction very nearby, at #930C.  ;)

Edited by IRF
Link to comment
Share on other sites

; because it was a few bytes too big

; I have extended the scope of the modification

 

;there are now free bytes 

 

ROPE_TABLE
x8300 DEFB 6*2+0,6*2+0,6*2+0,6*2+0,6*2+0,6*2+0,6*2+0,6*2+0
x8308 DEFB 6*2+0,6*2+0,6*2+0,6*2+0,6*2+0,6*2+0,6*2+0,6*2+0
x8310 DEFB 6*2+0,6*2+0,6*2+0,6*2+0,6*2+0,6*2+0,6*2+0,6*2+0
x8318 DEFB 6*2+0,6*2+0,6*2+0,6*2+0,6*2+0,6*2+0,6*2+0,6*2+0
x8320 DEFB 6*2+1,6*2+1,6*2+1,6*2+1,6*2+1,6*2+1,6*2+1,6*2+1
x8328 DEFB 6*2+1,6*2+1,6*2+1,6*2+1,6*2+2,6*2+2,6*2+2,6*2+2
x8330 DEFB 4*2+2,6*2+2,6*2+2,4*2+2,6*2+2,4*2+2,6*2+2,4*2+2
x8338 DEFB 6*2+2,4*2+2,4*2+2,4*2+2,6*2+2,4*2+2,4*2+2,4*2+2
x8340 DEFB 4*2+2,4*2+2,4*2+1,4*2+2,4*2+2,4*2+1,4*2+1,4*2+2
x8348 DEFB 4*2+1,4*2+1,4*2+2,4*2+2,4*2+3,4*2+2,4*2+3,4*2+2
x8350 DEFB 4*2+3,4*2+3,4*2+3,4*2+3,4*2+3,4*2+3

 

 

 

From here

X9316 ld c,(ix+rope1)              ;$1 this replaces the add a,(ix+rope1)

 ADD A,c

;remove the rope swing direction bit (bit 7)
res 7,a                                ; it helps to include the full modifications
ld l,a
ld H,High ROPE_TABLE     ; $83

; extract the data, 00001100b contains the Y-shift
ld a,(hl)                               ;grab data   hl=pointer to rope data
and 1100b
rrca                                      ;instant crash is this value is odd (no possibility with previous AND instruction)

; add Y-shift onto the Y-table offset
add  a,iyl
ld iyl,a

;extract the data, 00000011b contains the data for X-shift
ld a,(hl)
and $03                             ;$03=3=00000011B

 

; carry on removing excess code

 JR Z,L9350                     ;Jump if so
 LD B,A                            ;B is the count for rotations of the drawing byte (the rope drawing data bit)

 BIT 7,C                           ; right of centre?
 LD A,(IX+rope5)              ;$05;the drawing bit
 JR Z,rope_right              ;

 

rope_left:
 RLCa                             ;Rotate the drawing byte left once
 JR nc,hop1                    ;has the bit rotated around
 DEC (IX+rope3)             ;$03;Decrement the x-coordinate 
hop1: 

 DJNZ rope_left               ;
 JR SAVE_A                    ; saving "A" the continue

 

rope_right:
 RRCa
 JR nC,hop2                    ;has the bit gone full circle
 INC (IX+rope3)               ;$03;Increment the x-coordinate
hop2:
 DJNZ rope_right             ;

 

SAVE_A:

 LD  (IX+rope5),A            ;save the rotated drawing bit

 

;end of mods ;

There is now space here that needs filling with NOP up to  $9350

Link to comment
Share on other sites

Good stuff. It's probably always a good idea, when performing rotate operations, to hand over to the Accumulator wherever possible, instead of rotating one of the other registers (and especially avoid rotating an indexed offset byte).

 

Using A is more efficient both in terms of saving bytes (because there's no need to use shift opcodes) but also in terms of reducing the number of T-states that the operations take to perform.

 

(Incidentally, doesn't AND #7F do exactly the same thing as RES 7,A - but requires fewer T-states? ;) EDIT: It's small beer in the scheme of things, mind.)

Edited by IRF
Link to comment
Share on other sites

You probably noticed that the code listed, used labels for the offsets into the data.

e.g              ld a,(ix+rope5)

This usage of labels is something I have tended to do more and more over the years. It stems from needing to do rapid changes of data caused by changes in how I write something. By using labels it becomes an easy global change (in an assembler) to change an offset via the label.

In the case of JSW the rope data suffers from an overflow of data, and the solution (in my case) was to reassign the offsets and to move the allocation of one bit from bit 0 to bit 7. The changes needed in the code was minimal.
 

It also makes it obvious that it is rope data that is being used.


 

Link to comment
Share on other sites

  • 3 weeks later...

The ability to jump into certain wall blocks has been greatly reduced.

 

But not entirely eliminated though! I believe it is still possible to jump into/through Earth blocks on the descent part of a jump.

 

The fundamental reason why this is possible within the JSW game engine, is because when Willy is jumping, his y-coordinate is adjusted before a check is made for standonable cells beneath his feet. (In contrast, when Willy is falling, his y-coordinate isn't adjusted until after the check is made for platforms underneath his feet.)

 

For reference:

http://skoolkid.github.io/jetsetwilly/asm/8DD3.html

 

I can conceive of two possible fixes for this (although quirkophiles such as Dr Andrew Broad wouldn't thank me for it!):

 

(1) Rearrange the 'Move Willy (1)' routine, so that Willy's y-coordinate isn't adjusted until after the check for underfoot cell behaviour. (i.e. only proceed to adjust his vertical position downwards IF there is nothing underneath his feet to break his fall.) I haven't considered this in detail; it could be complicated because the code handling Willy's jumping and falling behaviour are interwoven within that routine;

 

(2) Replicate (a modified version of) the code at #8EBC-#8ED3, which detects a collision between Willy and an overhead Earth block, and resets his coordinates downwards accordingly, to eject him from the Earth block. This is intended to curtail a jump upwards through Earth blocks, but it also gives rise (inadvertently, I would imagine) to the infamous 'Innocent-Looking Block' behaviour.

 

I've tried out the second approach to a fix, and it works. ;) After the instruction at #8E00, but before the command at #8E03, insert the following code. (This requires a fair bit of consolidation to make the code fit, or else a JUMP to free space elsewhere in the code.) Note that when the program reaches here, the A register will hold the attribute byte for Earth blocks/wall tiles, as defined at #8DF7, and the HL register-pair will be pointing at the top-right cell of Willy's sprite (see #8DFE):

 

LD DE, #0040

ADD HL, DE Point HL at the right-hand cell below Willy's sprite.

CP (HL) Set the zero flag if the right-hand cell below Willy's sprite contains an Earth block.

DEC HL Point HL at the left-hand cell below Willy's sprite.

JR Z, earthleg If the right-hand cell below Willy's sprite contains an Earth block, then jump to the code which prevents him from jumping into it from a certain angle.

CP (HL) Does the left-hand cell below Willy's sprite contain an Earth block?

JR NZ, #8E03 If not, then resume executing the regular 'Move Willy (1)' routine (make the jumping sound, etc.)

 

That is then followed on immediately (if the left-hand cell below Willy's sprite does contain an Earth block) by:

 

earthleg:

LD A, (#85CF) Round Willy's y-coordinate down

AND #F0 to the nearest multiple of #10;

LD (#85CF), A this ensures that he is cell-row aligned, and standing on the Earth block which he would otherwise have jumped through.

CALL #8E9C Align Willy's attribute coordinates with his pixel y-coordinate. [i'm not sure that's strictly necessary in this context, but I've included it as a precautionary measure.]

JP #8ED4 Proceed to the 'Move Willy (2)' routine, which resets Willy's jump counter (#85D1) and then detects movement keypresses.

(N.B. The HL register-pair is now pointing at the appropriate cell to pick up underfoot conveyor behaviour.)

 

 

N.B. The above fix only prevents Willy from jumping into Earth blocks. It doesn't address the ability of Willy to walk into Earth blocks that are situated in certain positions in the vicinity of a ramp (e.g. Willy can walk down the ramp in 'On Top of the House') - that's a whole different kettle of fish!

Edited by IRF
Link to comment
Share on other sites

  • 1 month later...

 

The fundamental reason why it is possible [to jump into Earth blocks] within the JSW game engine, is because when Willy is jumping, his y-coordinate is adjusted before a check is made for standonable cells beneath his feet. (In contrast, when Willy is falling, his y-coordinate isn't adjusted until after the check is made for platforms underneath his feet.)

For reference:

http://skoolkid.github.io/jetsetwilly/asm/8DD3.html

 

I can conceive of two possible fixes for this (although quirkophiles such as Dr Andrew Broad wouldn't thank me for it!):

 

(1) Rearrange the 'Move Willy (1)' routine, so that Willy's y-coordinate isn't adjusted until after the check for underfoot cell behaviour. (i.e. only proceed to adjust his vertical position downwards IF there is nothing underneath his feet to break his fall.) I haven't considered this in detail; it could be complicated because the code handling Willy's jumping and falling behaviour are interwoven within that routine;

 

(2) Replicate (a modified version of) the code at #8EBC-#8ED3, which detects a collision between Willy and an overhead Earth block, and resets his coordinates downwards accordingly, to eject him from the Earth block. This is intended to curtail a jump upwards through Earth blocks, but it also gives rise (inadvertently, I would imagine) to the infamous 'Innocent-Looking Block' behaviour.

 

Further to the above, I have now implemented both of those methods for fixing the 'Through the Wall' bug.  The two methods are completely different in their execution, and each fix gives rise to some different, quirky and interesting side-effects.

 

The first method is implemented in the test file attached to this post:

http://jswmm.co.uk/topic/185-free-space-and-code-optimisation-in-jsw/page-20?do=findComment&comment=8311

 

and the second method is in place in the file attached here:

http://jswmm.co.uk/topic/196-dont-mind-your-head-while-walking-left-bug-fix-for-jsw/page-4?do=findComment&comment=8312

Link to comment
Share on other sites

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.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.