Jump to content


Member Since 23 Aug 2015
Offline Last Active Dec 10 2017 10:16 PM

Topics I've Started

Modified sprite-drawing code

08 November 2017 - 01:32 AM

In original JSW, at the instant when Willy collides with a guardian, that guardian is only drawn as far the graphical byte which collided with Willy. Furthermore, all guardians that appear subsequently in the current room's guardian list are not drawn at all in that moment. (That latter point means that composite guardians - for example the three-part Evil Priest Head or the Attic Centipede - are rendered incompletely at the time of Willy's collision with one component part of them*.)

In the attached file, all the guardians (and arrows and ropes) in the current room are drawn in their entirety at the moment when Willy is killed by colliding with one of them.

Note that in the attached file, the room still appears as 'empty' - without guardians, items or Willy - whenever Willy hits a Fire cell or falls a fatal distance.



EDIT: * Unless it is the last component part to be drawn which is the one that Willy collides with.

An Enhanced Teleport Routine for JSW

18 September 2017 - 11:28 PM

Please see the attached test file.  I've implemented a teleport routine, based on John Elliott's but in this case, each teleporter has six definition bytes, in turn:


Source room number

Source y-coordinate

Source x-coordinate

Destination x-coordinate

Destination y-coordinate

Destination room number


So, unlike in John's original routine, the exact position of the teleporter may vary between source and receiver room.  Or you could have a teleport which takes Willy from one part of a room to another part of the same room.


y-coordinates are specified in terms of (pixelsx2) from the top (it's probably best if these are cell -aligned i.e. a multiple of #10, although there are a couple of half-aligned examples in the test file i.e. multiples of #08, where Willy falls into or out of a teleporter; x-coordinates in terms of cell-columns in from the left column; all numbers are in hexadecimal.


The subroutine to implement this is at #9718-#9765 (CALLed from #8B70), and the teleporter data are stored at #9767 (number of teleporters in the game) and #9768-#97AF (12 x 6-byte definitions).

As part of the new code, there is a CALL to an existing subroutine at #8E9C, which is necessary to ensure that Willy's attribute coordinates remain aligned with his pixel coordinates.
Final technical detail: Each time Willy enters a teleporter, there is a CALL to the 'Play an intro message sound [and border] effect' at #96DE.  I haven't defined the input (A register) going into that routine, so it picks up the previous value stored in A (which happens to be the room number of the destination room).  As a result, the pitch (and duration) of the sound varies from room to room. e.g. if Willy teleports into a room with a high value for the room number, the noise has a relatively low pitch and long duration, etc.  (I recommend turning off the in-game tune to observe the variations in the noise associated with the teleporters.)




There are about twelve teleporters inserted into the test file.  They take Willy on a tour of all the 'Forbidden Holy Grounds' in the original game, and then he ends up on The Bow of his Yacht.



Setting a rope's horizontal position by pixel

07 September 2017 - 11:41 PM

Please see the attached test file.


PREAMBLE: In 'Jet Set Mini', I managed to implement perfectly laterally-inverted ropes, partially by changing the position of the top segment of each rope within its host cell.  (i.e. In original JSW, the top rope segment occupies the leftmost pixel in the defined start-column; whereas in 'Jet Set Mini' the top rope segment occupies the rightmost pixel.)


This test file extends that concept further.  I have slightly rewritten the 'Draw the Ropes' routine, so that the precise horizontal pixel-position of the top of each rope in the game may be specified separately. i.e. on a 'rope instance' basis.  The pixel position of the top segment is stored in the highest three bits* of Byte 2 of the Rope Definition (which is copied over, from the second byte of each rope's specification in the room's guardian list, when the 'Room Setup' routine is executed).


The value of that three-bit number is then translated into the correct pixel to infill for the top segment, using a similar principle to that which is used in Manic Miner to draw the remaining pixels of air supply at the right-hand end of the air bar (except that I've used the RLC E command here, instead of RRC E, and there is no setting of additional bits during each pass through the DJNZ loop).



Within the the start-up room (Swimming Pool) in the attached file, there are eight** ropes which are very closely spaced horizontally (only three pixels apart).  I have called this effect a 'Swinging Curtain', as that's what I think it looks like!


Note that the game is slowed down somewhat in the room in question, because of the need to perform eight complex rope-drawing operations during each time-frame.





* One consequence of this change is that you lose the ability to create an 'Invalid Rope' like the one in the 'Overgrown MegaTree' in 'Jet Set Mini' (the top segment of which is drawn further down the screen than is usually the case, because I assigned an 'invalid' value [greater than #1F] for the x-coordinate of the top segment of rope, in the room's guardian table).  However, that's probably not a great loss - Invalid Ropes can be very 'quirky', especially if they extend down beyond the boundary between the top and bottom half of the playing area, which causes segments to appear in strange places (the one in 'Jet Set Mini' is sufficiently short to prevent this from happening).



** Note that because there are eight ropes present in the room, it can be quite difficult to dismount the ropes/curtain!  The 'Draw the Ropes' routine usually allows Willy 16 time-frames to elapse, after jumping or falling off a rope, before he can be caught by a rope again.  However, with eight ropes being drawn consecutively in each time-frame, that reduces to two time-frames!  (Although that is not a result of the changes that I made in the attached; it is a curious feature of the JSW game engine, and would be the case in any JSW room with eight ropes.)

A Manic Miner 'Special Guardians' test file (JSW64 engine)

05 September 2017 - 10:46 PM

Please see the attached test file, based on the JSW64 game engine, which features experimental/novel implementations of each of the four 'special' Manic Miner 'guardian' types.
The opening room, a modified version of 'The Bridge', features an unprecedented mixture of 'standard' Skylabs, and Droplets of various types, all operating simultaneously.  (They don't actually pose a threat to Willy in this test file, unless he jumps up and hits one.)
All of the Droplets display distinct behaviour:
- The white Droplet doesn't have any horizontal displacement in between consecutive incarnations, and drops down consistently in the centre of the screen;
- The yellow Droplet has a horizontal displacement of 16 columns, so that it alternates between two positions half a screen-width apart;
- The cyan Droplet has a rightwards horizontal displacement of 8 columns, so it progresses from left to right across the screen through four possible 'drop zones', just like the classic Skylabs in Manic Miner;
- The green Droplet has a leftwards horizontal displacement of 4 columns, so it progresses from right to left across the screen through eight possible 'drop zones'.
N.B. the starting columns of all four Droplets have been carefully selected so that they shouldn't ever collide!
Angry Eugene:
If you walk rightwards from the start-up room and enter 'The Off Licence', there is a vertical guardian which displays 'Eugene' behaviour, but with a twist...  Your mission is to try to collect the item and escape safely from the room (it's a 'No Kamikaze' room, so the item will be reinstated if Willy loses a life before exiting).

I suggest that you first try walking rightwards into the room without stopping, proceeding under the guardian and up the ramp, then jumping to collect the single item as soon as possible, and watch how events proceed.
Then try taking a bit more time before collecting the item, and see the difference.


Solar Beam:
If you walk leftwards from the start-up room into 'Under the MegaTree', you can see that I have implemented a fix for the Solar Beam Bug which meant that, in original Manic Miner, the Solar Beam did not always kill Willy as soon as the air supply ran out. i.e. in this test file, the Solar Beam does kill Willy at the instant when the air supply is depleted to zero.  Ditto for the Kong Beast (see below).
Kong Beast:
There is also a Kong Beast in 'Under the MegaTree' that displays a novel feature, the idea for which was inspired by the following exchange between John Elliott and Andrew Broad in a post on the Yahoo Group:

Andrew Broad: "When you complete a cavern, the air empties faster and at a higher pitch than in MM."
John Elliott: "Because there's no score."

Andrew Broad: "And thus no incentive to kill the Kong Beast, other than the satisfaction of seeing it turn yellow and fall upside-down with that 
sickly falling noise! ;-)"

Well, in the attached test file, there is an incentive to kill the Kong Beast - because it also saps Willy's air supply in 'Under the MegaTree'!  See how quickly the air supply is being depleted in that room, even when Willy isn't standing in the Solar Beam!  (N.B. The 'lethality' of the Solar Beam and of the Kong Beast can be set independently of each other.)
In order to survive in 'Under the MegaTree' for more than a few seconds, it is necessary to flip the Switch (the yellow thing in the branches at the top-left, which uses 'Willy's head' as its sprite) and thus kill the Kong Beast.  Note that there is a handy flashing Portal which provides a shortcut up to the Switch from the bottom of the screen, and Willy's progress is further assisted by the room's Portal Patch Vector, which automatically sets him jumping leftwards as he exits it - another technical novelty, I believe? - so that he lands just a few steps away from the Switch!


Note that there are also a few bug fixes implemented in the attached test file, including some tweaks to the Kong Beast code to make it more 'generic' (for instance, making the Kong Beast's animation dependent on the global 'tick' counter rather than the current air supply, so that Kongs are still animated even if they appear in rooms without an air supply limit), and a patch for the bug in JSW64 which causes the Air Supply bar to become invisible (albeit still operational!) when you pause and unpause the game (something which remains in Dr Andrew Broad's 'to do' list for his 'Advanced JSW/MM Trainer project!).
A final word: I was wondering whether the scale of the interventions in the attached file (if they were extended to all six JSW64 variants) would mean that it could perhaps be considered to be a 'Hack Level 13' of the JSW64 game engine?  Any thoughts?

Manic Miner Air Supply - a more refined approach

01 August 2017 - 05:06 PM

There is a misconception in Dr Andrew Broad's otherwise excellent 'Manic Miner Room Format' document, regarding the matter of Miner Willy's Air Supply.  Furthermore, John Elliott's JSWED editor seems to have followed Andrew's lead on the matter.  And both parties were, in all likelihood, "led up the garden path" by Matthew Smith's original choices for the values of the initial air supply in the original MM caverns.


Here is the pertinent excerpt from Andrew Broad's Manic Miner Room Format document:



Offsets 700 to 701: Air

The amount of air you have in a room is held in Offsets 700 and 701:


  • The value held in Offset 700 is a+32, where a is the column that the air goes up to (effectively, you have a-4 characters of air, as the air starts at column 4). The default value for Offset 700 is 63 (i.e. a=31), but in many of my caverns, I give you a reduced air supply! :->
  • The value held in Offset 701 is the number of pixels of air you have (in addition to characters of air, as encoded by Offset 700), represented as one of the following bytes (shown in binary to help you visualise it):
    10000000 (denary 128)
    11000000 (denary 192)
    11100000 (denary 224)
    11110000 (denary 240)
    11111000 (denary 248)
    11111100 (denary 252)

    There are bugs associated with using 00000000, 11111110 or 11111111 as the value for Offset 701, so it's derecommended (and my Manic Miner Screen Editor doesn't allow it - actually, it does allow 11111110 because I only discovered that this value was problematic after I released MMSE):

    • Using 00000000 (denary 0) causes a fairly harmless glitch in the graphics (see Room 10 of Manic Miner: The Buddha of Suburbia, "The BUDDHA OF SUBURBIA : suburbs");
    • Using 11111110 (denary 254) or 11111111 (denary 255) confuses Manic Miner when it is supposed to subtract a character of air from Offset 700, resulting in an infinite amount of air and causing the Spectrum to lock up when you exit a cavern. I used this trick in the final room of both Manic Miner 4 and Manic Miner: The Buddha of Suburbia, but it's not to be recommended, especially not in earlier levels! ;-)


The possible values for Offset 701 recommended by Andrew are not linear, or proportionate to the number of pixels of air displayed in the final character of the air bar.  The number of pixels that are initially drawn within the final character of air are as follows:


10000000 (denary 128) - 3 pixels
11000000 (denary 192) - 5 pixels
11100000 (denary 224) - 6 pixels
11110000 (denary 240) - 7 pixels
11111000 (denary 248) - 7 pixels
11111100 (denary 252) - 7 pixels


(The only difference between the last three values, is a small variation in the number of time-frames which elapse before the first pixel of air supply is erased from the air bar.)


In JSWED, John Elliott has established an Air Supply drop-down menu which allows possible values from 0 to 161, representing 6 possible values for each of the 27 available characters of air supply. i.e. seemingly in accordance with Andrew's recommended values above.  [N.B. A value of 162 may be selected in a JSW64 game, but this assigns a value of #FF to Offset 701, as an indicator that the room/cavern does not have a limited air supply.]


Now, as it happens, all of Matthew Smith's original caverns contain a value at Offset 701 which matches one of Andrew's values.  The specific values are detailed here: http://skoolkid.gith...riableAirSupply


However, any value could be selected for Offset 701 (this can be done via the hex editor in JSWED), as long as it is a multiple of 04.  Which, as Andrew points out, rules out denary 254 or denary 255.  (They cause the Spectrum to lock up when Willy exits a cavern, because the air supply countdown is decreased in decrements of 4, and so Offset 701 never reaches the target value of zero.)  Andrew is also correct about the harmless glitch caused by selecting an initial value of zero for Offset 701.  (The glitch occurs because, when the 'Decrease the air supply' routine at #8A3C is run in that circumstance, the number of characters of air supply is decremented before the routine gets a chance to wipe the pixels from the first [rightmost] character of air supply - the whole bar of air having being drawn in the first instance by the 'Cavern Setup' code which starts at #8691).


I believe that Andrew must have - without the benefit of SkoolKid's excellent MM disassembly being available at the time, of course! - mixed up the possible values of the A register, emerging from the AND #E0 gate at #8A55, with the possible values of the E register which is used to determine how many pixels of air supply to draw in the rightmost character of air (individual bits of E are set, via a DJNZ loop, after A has been divided by #20 and fed into the B register - see #8A57-65).





There is a more refined possible approach to the gradation of the air supply.  The air supply is graded at three levels, listed below in decreasing order of magnitude:


- The number of characters of air within the air bar (derived from Offset 700);

- The number of pixels of air within each character of air (determined by the value of Offset 701, in steps of #20, and so eight pixels disappear before the byte wraps round past zero and the character is fully erased);

- The number of time-frames that elapse between the removal of consecutive pixels of air supply (eight time-frames, equating to a decrease in the value of Offset 701 of 8 x #04 = #20).


Andrew's approach involves assigning values to Offset 700 in a linear manner, but his suggested values for Offset 701 are a non-linear hybrid of bullet-points 2 and 3 above.


My suggested alternative would be to use the following possible values for Offset 701:


00100000 (#20, denary 32)

01000000 (#40, denary 64)

01100000 (#60, denary 96)
10000000 (#80, denary 128)

10100000 (#A0, denary 160)
11000000 (#C0, denary 192)
11100000 (#E0, denary 224)
11111100 (#FC, denary 252), or alternatively 00000100 (#04, denary 4)

(The final value would fall slightly outside of the linear pattern, causing a pixel-increment to occur either one time-frame early or one time-frame late; but this is necessary in order to prevent the visual glitch which Andrew reported when a value of 0 is selected.)


This alternative air-supply regime would translate into possible values, in an equivalent JSWED drop-down menu, of 0 to 215,  representing 8 possible values for each of the 27 available characters of air supply.  (In which case, a value of 216 should be used for a room without a limited air supply.)