-
Posts
608 -
Joined
-
Last visited
Everything posted by Norman Sword
-
Decided to test concept. One hour later I had an up and running 120 room version. Both completely independent and both can be remapped. No enthusiasm for doing so. Both sets or rooms are free to cross to the other at any point. This is a full 120 room version. I can not think of any layout restrictions.
-
Ramblings:- concerning the last part demo program. . I got bored with the standard 64 room limit, plus the fixed memory restrictions, so decided to change how the rooms where stored. . Change 1) Leave the room data alone (e.g. the tile definitions, sprite definitions, room names) but split the room shapes off from this data and compress. I ended up with 60 room data pages and 2 sets of 60 room shapes. This edit has for every room shape, a shadow room shape. It was in the file before last, that I uploaded. Which was why some room shapes changed. . Change 2) I decided to then compress the room data. Not an extensive compression, but enough data was removed so in this version I had 2 sets of room data, and 2 sets of room shapes. This was 60 rooms, and 60 rooms shadowed. The change from one set of rooms to the other permitted new sprite definitions and new tile definitions and new room names. It was effectively a 120 room game with no attempt at changing the alternate room layout. The two sets of rooms still contained a common overall layout and a common set of room keys. . Sidetrack Norman sword Key storage . It is easy to compress the room data, and therefore easy to increase the room count upwards. The simplest method is to ditch the constrictive usage of page boundary data and move to indexed data with variable size. This permits every room to be whatever size it requires. The room exits use a full byte so it is easy to have room numbers greater than sixty three. We can have room numbers up to two hundred and fifty five. But we do not have the memory to store that many, so a realistic figure of one hundred and twenty seven is possible. . The rooms can easily be drawn and stored. The biggest challenge lies in the storage of the keys. Matthew implemented a six bit storage limit into the room numbers stored in the two pages of stored data for the keys. Some attempts have extended this table by adding a new page of data. (256 bytes) When only 32 bytes where needed. What was missed was the simplicity of just using a one bit variable that indicates upper or lower sets. Rooms naught to sixty three are stored in the key list exactly as of present, occupying the upper half of the key page. Any room that is over sixty three, uses the lower half of the table. Its value "AND'ed" with sixty 63 and uses the same data space, but is confined to the lower half. . I use the term "the lower half" when in reality I am storing one set of key data from offset 255 downwards, and the other set of data from offset 0 and storing upwards. As long as the two sets of data do not overlap. Then the two sets of data can happily exists in the same data space. . The changes needed to some of the other routines are minimal. (broad outlook on changes, no detail) :- The reset the keys to uncollected, changed to reset the full page, as opposed to just the top part. :- the number of items uncollected is the top page value - the bottom page value :- The key collection routine can be modified to search upwards or downwards depending on the value of the room number. e.g the key flag :- The drawing of new rooms from the value obtained from room data, sets which set of keys needs to be searched. Rooms 0-63 search upper key list, rooms 64 to 127 search lower key list. e.g set a one bit key flag. Which is used by the key collect and draw routine I do not check the key list in a similar fashion to the original. On room expansion I generate a new key list for the current room. This is the key list used to check for collected items and also to animate the keys. The method I use to generate this new key list is similar to the method outlined above. For the lower rooms I search the top of the key list, for rooms above 64 I search the bottom of the list. . This limits the total key count to 256, but other versions have this restriction. It took me around two hours to implement this data change and also implement the usage of both sets of data. . Having implemented the above change for the keys with each block of 60 rooms having its own tile/sprite definitions/room name, its own room shape and now its own key storage area. It is now possible to implement the next change. (not implemented). . Change 3) The logic added for the shadow routines can be removed. One set of rooms no longer needs to have any reference to the other set of rooms. Both sets of rooms are now free in every aspect. And we can map out a 128 room game I have about 99.9% of the above written, but at present no urge to implement change 3. (which is mainly deleting routines) At present I am editing the version with 120 rooms, but each set is an overlay of the other set. This restricts room layout to enable free switching between the two sets. The designing and editing is still done by using the standard 64 room version. What my program does is incorporate the data from two games, and merge them together. . BASIC As I said above I compressed the rooms because I was reaching the fixed limit of memory that I had available. I was experiencing graphics being overwritten. So I wrote a routine in BASIC to compress the room graphics and output the data in assembler form. I would have liked to say this routine was simple to write. And perhaps it was, the BASIC is a few lines short of 1000 lines and took a week to write. (not in one go) . The BASIC file was edited along these lines . The basic takes a game file and from it extracts the game data, in the Format that is similar to the Matthew room data layout below. This was changed to extract the room data (the shape of the room) into another file after doing a RUN LINE COMPRESSION on the file. This was then changed to have macro's that allowed both versions to be used by the assembler in one file. This was again changed to enable vertical and horizontal RUN LINE COMPRESSION for the assembler file. Another change enabled the stairs and conveyors to be incorporated into the VERTICAL RUN LINE COMPRESSION. Yet another change saw the output of the keys data in a separate file Yet another change saw the program output the data from two files at the same time. The original data and the shadow data Another change and the file was compressing and deleting the unwanted room graphics/exits/room name/unused sprites etc. Then the final change was the merging of both sets of key data into a single key data file. . I am always amazed at how fast modern PC's can do this amount of processing and output. The time between the start and finish of the extraction process is measured in fractions of one second. Yet the output is measured in around 110k of source code data . Whilst I was changing the data, I needed to change lots of parts of the assembler source file in parallel. And I was amazed when I wrote the final leap into having all of the data compressed that it worked first time. . . . example of the size of the data for the room shape. . As stored by Matthew for The Off Licence ; reduced from the uncompressed 512 bytes used in Manic Miner ; this is two bit run line coding ;128 bytes,#80 49152 DEFB 0,0,0,0,0,0,0,0 ;Room shape 49160 DEFB 0,0,0,0,0,0,0,0 49168 DEFB 0,0,0,0,0,0,0,0 49176 DEFB 0,0,0,170,170,170,170,170 49184 DEFB 0,0,0,128,0,0,0,2 49192 DEFB 0,0,0,128,0,0,0,2 49200 DEFB 0,0,0,140,0,0,0,2 49208 DEFB 0,0,0,128,0,0,0,2 49216 DEFB 0,0,0,128,0,0,0,2 49224 DEFB 0,0,0,128,0,0,0,2 49232 DEFB 0,0,0,128,0,0,0,2 49240 DEFB 0,0,0,170,0,0,2,170 49248 DEFB 0,0,0,0,0,0,0,2 49256 DEFB 0,0,0,0,0,0,0,2 49264 DEFB 0,0,0,0,0,0,0,2 49272 DEFB 85,85,85,85,85,85,85,85 . What it is possible to compress to. (variable size) . Data as stored by me for the same room. The Off Licence ;this is vertical and horizontal run line coding ;26 bytes, #1a 102 bytes smaller db #25,#DF,#2D,#5F,#2D,#4C,#97,#33 db #67,#D7,#1E,#3F,#2B,#93,#3F,#0D db #C0,#3F,#3F,#1C,#83,#0A,#84,#3F db #1F,#5F ; Matthews storage of the basic room data ; 128 bytes #80 49280 DEFM " The Off Licence " ;Room name 49312 DEFB 0,0,0,0,0,0,0,0,0 ;Background 49321 DEFB 68,255,222,108,136,18,64,4,0 ;Floor 49330 DEFB 22,34,255,136,255,34,255,136,255 ;Wall 49339 DEFB 5,248,136,158,189,189,158,136,248 ;Nasty 49348 DEFB 7,3,0,12,0,48,0,192,0 ;Ramp 49357 DEFB 67,51,255,51,0,255,0,170,0 ;Conveyor 49366 DEFB 0 ;Direction 49367 DEFW 24371 ;pos 49369 DEFB 12 ;Length 49370 DEFB 1 ;Direction 49371 DEFW 24535 ;pos 49373 DEFB 4 ;Length 49374 DEFB 5 ;Border 49375 DEFB 0,160 ;Unused 49377 DEFB 24,24,60,126,98,98,98,126 ;Item 49385 DEFB 1 ;left 49386 DEFB 0 ;right 49387 DEFB 0 ;above 49388 DEFB 0 ;below 49389 DEFB 0,0,0 ;unused 49392 DEFB 10,138 ;guard 1 49394 DEFB 12,29 ;guard 2 49396 DEFB 44,39 ;guard 3 49398 DEFB 255,0 ;Terminator 49400 DEFB 0,0 49402 DEFB 0,0 49404 DEFB 0,0 49406 DEFB 0,0 . all that is needed. variable size ;82 bytes (this might be an edited version of the above) ;46 bytes smaller . db #09,"The Off Licenc",+"e"+#80 db #00 ; back db #44,#FF,#DE,#6C,#88,#12,#40,#04,#00 ; floor db #16,#22,#FF,#88,#FF,#22,#FF,#88,#FF ; wall db #05,#F8,#88,#9E,#BD,#BD,#9E,#88,#F8 ; nasty db #07,#03,#00,#0C,#00,#30,#00,#C0,#00 ; ramp db #43,#33,#FF,#33,#00,#FF,#00,#AA,#00 ; convey db #45,#18,#18,#3C,#7E,#62,#62,#62,#7E ; (conv/ramp/border)/item db #01,#00,#00,#00; Paths db #0A,#8A; guard 1 db #0C,#1D; guard 2 db #2C,#27; guard 3 db #FF; Terminator Matthew per room 256 bytes ; this room compressed 26+82= 108 bytes + 4 for pointers ; 144 bytes smaller query on terminology. The middle sprite in Mondrain, is used extensively in conjunction with the Monks. The shape and format of the sprite is typical of medieval parchment scrolls.
-
Re Gaurdians aura This version has a playable "Swimming pool" This is another edit of my "delete me now" file. Only Rooms of interest (reference by the normal room names) Swimming Pool Guardian aura/colouring The Chapel homing sprite The Bathroom arrow volley A lot of other rooms have had minor changes This is a bigger edit of the last file I uploaded. This might look like a normal JSW file but it contains 120 rooms, with each of the normal 60 rooms, having a fully definable clone room. This version could be remapped to be a playable 120+ room game. The game is set to swap between each version of rooms. JSW ALTERED 1.tap
-
I have added a note to the top of what I wrote, concerning the SET 7,L opcode.
-
Rough figures... ;**************************************** ADDENDUM **************************************** I originally used the terminology of REM'd out for the SET 7,L in the code. This is only possible in an assembly listing and is not possible with situations such as this. The nearest equivalent would be inserting NOP,NOP. However this makes a slight change in how the text is handled. The stream of text going through the print routine could have any value, and might be over 127 With that in mind, it would make a far better change to use RES 7,L as the alternative to SET 7,L ******************************************* . .From listing of JET SET WILLY Numbers in HEX . 9691 LD H,$07 9693 LD L,A 9694 SET 7,L ;could delete NOP'd >>> use RES 7,L 9696 ADD HL,HL ;*2 9697 ADD HL,HL ;*4 9698 ADD HL,HL ;*8 9699 LD B,$08 . Changing the opcode at #9691-- the LD H,07 setting H to = 0 1 2 3 4 5 6 7 etc muliplied *8 0000/0800/1000/1800/2000/2800/3000/3800 up to f800 setting bit 7 of L and multiplying by 8 gives an offset of 400h . so by combining we can have offsets of 0000/0400/0800/0c00/1000/1400 up to Fc00 . by setting either we have #20 addresses we can use. anything below #8000 is taken by buffers/screen/rom Giving usable addresses such as (in hex) h= 10 11 12 13 14 15 16 17 8000,8800,9000,9800,a000,a800,b000,b800 with RES 7,L REM'ed out 8400,8c00,9400,9c00,a400,ac00,b400,bc00 with SET 7,L left in h= 18 19 1a 1b 1c 1d 1e 1f c000,c800,d000,d800,e000,e800,f000,f800 with RES 7,L REM'ed out c400,cc00,d400,dc00,e400,ec00,f400,fc00 with SET 7,L left in ;---------------------------------------------------------------------------------------------------------------------------- The font needs to be stored at these addresses (data from above adjusted for font position) e.g.+#100 h= 10 11 12 13 14 15 16 17 8100,8900,9100,9900,a100,a900,b100,b900 with RES 7,L REM'ed out 8500,8d00,9500,9d00,a500,ad00,b500,bd00 with SET 7,L left in h= 18 19 1a 1b 1c 1d 1e 1f c100,c900,d100,d900,e100,e900,f100,f900 with RES 7,L REM'ed out c500,cd00,d500,dd00,e500,ed00,f500,fd00 with SET 7,L left in ;----------------------------------------------------------------------------------------------------------------------------- Plenty of memory addresses to play with (back to decimal) I would assume you would use a short font, e.g. just ASCII 32 up to ASCII 127 or less I see no point in ASCII above 128 or below 32 The stored font then needs to sit 32*8 above the base page (listed above) e.g. +256 with a font size less than 800 bytes Stored font is (128-32)*8=768
-
The terminology that I used was "Mid Sprite bounce". Indicating a bounce in the mid part of its path. NOTE I keep on using Mid and not Middle. Mid has a multitude of definitions Its preposition definition is --- in the course of --- You define a bounce point in the course of the sprite path.
-
Yes an increment of IX. The code must also copy the y position.....Which it can do when setting the arrows phase in room set up.. (different from what I have at present... So I will change my own code) If a pair of arrows are defined and they are facing each other and cross on the screen. Then one needs setting as even and the other odd. (x position) Erroneous spelling noted. The assembler code is 540k of ASCII text. It has become difficult to read and bits and pieces get missed.
-
The seven empty slots. Which because of the code that double up arrows, gives fourteen arrows in that room. Of note it only uses ONE guardian definition, the others are defined by the position. E.g. the code below is all it takes in the room set up. But first a quick run down of my thoughts... bit 0 gives the arrow bug . but just taking the first 16 values and removing that bug leaves values 00,02,04,06,08,10,12,14 . we also have a feature/bug that stops the code working on the extremes of chars, so values of 00 or 14, should also be avoided. leaving 02,04,06,08,10,12 = 6 values from the first 16. or for the full screen playing area 16*6 values. 96 values from 256 in total. . I fail to see why this is used. If the arrow had been confined to a fixed position within the char. Then only four bits are needed to define an arrow. The other four bits could be used for any multitude of applications. . At present an arrow is defined by a fixed guardian. If a JSW2 style volley is wanted then each arrow would need its own guardian slot/definition. . By juggling those four bits a shift can/could be introduced into the fixed timing phase of the arrow. (done at room set up) This then permits one guardian to be defined as having up to 16 sub classes, just by allowing a phase change on just the one guardian definition. . patched into the room set up, after testing for an arrow type guardian. With no attempt at reducing the code size. ld a,(iy+arrow_y) ld b,a and 15 add a,a add a,a add a,(iy+arrow_x) ld (iy+arrow_x),a ld a,b and $f0 add a,8 ;middle of char ld (iy+arrow_y),a
-
Re arrows:- The arrows, my first play with them introduced a second arrow into the same guardian slot. Mentioning wasted bits I decided to implement something I had thought about concerning the arrows. This file shows what the wasted bits can do. Only demonstrated in the bathroom. This arrow demo, is tagged onto a file that keeps on being added to. (it needs deleting) mega volly.tap.tap
-
I amended the routine the handles depression into a block for ramps. It was not listed because it was another problem, separate from the ramp code. Plus my version can not be used because it uses subroutines and the routine itself is another subroutine. I would have needed to rewrite it.
-
;very little difference to the other version. ; ;but this has ;1) the addition of cell blocking to stop up and down movement via stairs into blocks ;2) changes in logic for jumping. ;3) removal of some data from the data table ; ; some of the data tables entries can be calculated by code. But the overhead of the code is bigger than the data table entry ;e.g entry for (ix+ramp_final_adjust)= (ix+ramp_where_1)-(ix+ramp_step) ; ;set variables for these offsets ramp_step equ 0*2 ramp_where_1 equ 1*2 ramp_where_2 equ 2*2 ramp_adjust equ 3*2 ramp_final_adjust equ 4*2 ramp_animation_reset equ 5*2 ; ;left data followed by right data left_data DB -1, 1 ;0 STEP TO NEXT animation FRAME - replaces inc or dec DB $1f, $22 ;1 POSITION OF RAMP 1 - ramp walk up DB $41, $40 ;2 POSITION OF RAMP 2 - ramp walk down DB -1, 2 ;3 DIRECTION TO ADJUST HL - where to check vertically db $20, $21 ;4 FINAL ADJUST - final adjust of willy to his new moved to position DB 3, 0 ;5 ANIMATION RESET for next frame ;----------------------------------- ; ;8FBC: Move Willy (3) ; Used by the routines at 8DD3 and 8ED4. This routine moves Willy ; left or right as necessary. RAMP_LOGIC ;L8FBC LD A,(ROPE_STATUS) ;L85D6;rope status indicator DEC A ;Is Willy on a rope? RET P ;Return if so (Willy's movement along a rope is handled at 935E) LD A,(L85D0) ;L85D0;Willy's direction and movement flags BIT 1,A ;Is Willy moving? RET Z ;Return if not ;not on a rope, but moving ld ix,left_data AND $01 ;Is Willy facing left? JR nz,set_left ;go if so 1=LEFT, 0=RIGHT inc ix ;else move IX to right data set_left: ld c,a ;save direction facing LD HL,(WILLY_ATT) ;L85D3; Willy's attribute buffer coordinates ; is the animation still within the same ATT squares ld de,WILLY_ANM ld a,(de) ;(WILLY_ANM);L85D2 ;Willy's animation frame at 85D2 add a,(ix+ramp_step) ;-1 OR +1 step to next animation ;if it was 0 then and now -1 ;or if it was 3 then now 4 ; in both cases bit 2 is set BIT 2,A ;check limits JR NZ,RAMP_CHK ;L8FDC ;move Willy's across a cell boundary ;if here still contained within the same animation (att) square, but different phase of animation LD (DE),A ;WILLY_ANM RET ; Willy now needs to move left or right and move into new attribyte squares ; this movement also needs to handle the stairs and check for their presence RAMP_CHK: ; three final outcomes for bc ; going up bc=-32 ; going down bc=+32 ; no ramp/blocked bc=0 push hl ;save for later ; all de increments are positive so preload D ld d,0 ; if jumping ignore ramp checks LD A,(AIRBORNE) ;L85D1 OR A ;Is Willy jumping? JR NZ,null_offset ;Jump if so ;not jumping so check for stairs ld a,(RAMP_DIR) ;L80da ;either 0 or 1 ; in the original JSW this value is 0 or 1 (my versions use other bits. so get rid the extra bits) and 1 ;get rid of the other bits ; this condition swaps on left and right movement cp c ;set the condition for where to check ;assume going up ramp ld bc,-32 ld e,(ix+ramp_where_1) jr nz,ramp_decided ; if here going down ld bc,+32 ld e,(ix+ramp_where_2) ramp_decided: add hl,de ; add offset to find ramp/stair square ld a,(RAMP) ;L80C4 sub (hl) ; is a ramp here ? ;if ramp not found then no offset needed jr nz,null_offset ;on a ramp is it going down? or b ;the direction, taken from BC=+32/-32, "A" must have been 0 jr nz,found_ ;branch if going up ;going down so locate the possible blocking tile LD A,L ADD A,(ix+ramp_step) ;step across to possible wall LD L,A ;is the wall blocking descent ld a,(WALL) ;L80B2 cp (hl) jr nz,found_ ;a wall is blocking going down ramp- so remove ramp offset - and walk horizontally along ramp/wall : : ; come here for no offset-or no ramp action null_offset: ld b,d ; ld c,d ;bc=0, no ramp so no offset/shift found_: pop hl ;retrieve WILLY_ATT add hl,bc ; add the possible ramp displacement ld a,(WALL) LD B,A ; ld e,(ix+ramp_adjust) ;d is still 0 ld a,l and 31 add a,e ; move across ;if negative (-1) then jp m,GO_ROOM_LEFT ;L948A ; if 32, then also off screen bit 5,a jp nz,GO_ROOM_RIGHT ;L949E ld a,l ; restore full x position (which has part y position embeded) add a,e ld l,a ;still on screen bit 1,h jr nz,ignore_this ; additional check if moving up a ramp; which checks out of line for willies head ;c can be -32 +32 or 0 bit 7,c jr z,hor_or_dwn ;going up find the tile to check ld e,a sub (ix+ramp_step) ; the direction we are moving ld l,a ;hl adjusted to head tile ld a,b ; the wall tile value cp (hl) ;wall tile? ret z ;return path is blocked ;adjust back ld l,e hor_or_dwn: ; move vertically and check the squares ; after the initial add hl,bc and possible head check ; this checks downwards in a line ; ;change logic if jumping downward, willies head can pass through wall block call jump_fix ;z=moving down ld a,b jr z,ignore_this ;zero indicates logic change-- ignore this tile cp (hl) ;head ;wall tile? ret z ;return path is blocked ; resume checking vertically down ignore_this: ld e,$20 ;D is still 0 ADD HL,DE ;move hl down one row ; ;(y+0) if Willy is on or about to up a ramp ; ;(y+1) if just walking or ; ;(y+2) if Willy is walking down a ramp CP (HL) ;foot ;wall tile? RET Z ;Return path is blocked LD A,(WILLY_Y) ;L85CF; y-coordinate (Y) ; bc held the ramp shift (b has been re-used but c is still the ramp shift) SRA C ; halve the value from ;c 32>16 ;c 0>0 ;c-32>-16 to get ramp y-shift ADD A,C ; y-position + ramp y shift LD C,A ; save in C ; this addition is changing logic depending on movement (jumping) call jump_fix ;z=moving down ; if jumping downward this square MUST be checked jr z,force_this ; otherwise check if willy occupies 3 squares ld a,c AND $0F ; JR Z,ONLY_TWO ;Jump if not force_this: LD A,b ;ATT wall tile ADD HL,DE ;point hil at the cell one lower ; Addendum for the bottom of the screen... Jumping downward and cell aligned can process of the screen ; it is easier to capture/stop problems before they happen BIT 1,H JR NZ,offscreen ; ;(y+1) if Willy is on or about to up a ramp ; ;(y+2) if just walking or ; ;(y+3) if Willy is walking down a ramp CP (HL) ;beneath ;Is there a wall tile down there? RET Z ;return path is blocked offscreen: OR A ; SBC HL,DE ; move back to feet position ;if here then Willy has been allowed to move up or down a ramp- walked along or jumped into a new attribute square. ; so save all the new parameters ONLY_TWO OR A ld e,(ix+ramp_final_adjust) SBC HL,DE ; back to final head position (free to move here) LD (WILLY_ATT),HL ;L85D3;Save Willy's new attribute buffer coordinates LD A,(IX+ramp_animation_reset) ; the animation frame LD (WILLY_ANM),A ;L85D2 LD A,C ;Willy's new pixel y-coordinate LD (WILLY_Y),A ;L85CF RET ;----------------------------------------- jump_fix: ld a,(JUMP) ;L85d5 sub 12 ret c ld a,(AIRBORNE) dec a ret
-
Nice piece of code. My only editing of the original code was to stop the type of guardian being changed whenever the original horizontal code was called. This was because my homing sprite called the horizontal movement whenever it wanted to move horizontally. The original code changed the guardian type. It is noted that the guardian type in your code is not modified. For clarity on your code it would benefit from a few additions regarding the usage of bit 7 (direction). This bit is being toggled in several places, with no mention as to why. e.g. XOR #80 ;restore direction (bit 7) which was inverted XOR #E0 ; invert direction (bit 7) and invert animation bits (6 and 5) and finally for clarity , an explanation of what the carry bit is being used for. ; the direction bit (bit 7 = #80) must be taken into account ;animation right adding #20 #80, #a0, #c0, #e0 carry clear with each addition but not #eo+#20 = #00 ; left adding #e0 #60, #40, #20, #00 carry set with each addition but not #00+#eo = #eo
-
This is also probably the bug the lets Willy move into the floor/wall tile when jumping right into the wall gap (next to the priest) in the "First Landing" . Again the check for beneath his feet incorrectly checks the tiles beneath his feet and not the tiles his feet are about to land on. Like so many other parts of the code, other checks can/could prevent this.
-
What Logic dictates and what actually happens. . . The black squares represent wall tiles . . Left block diagram: part 1: willy occupies the red squares and is trying to move upward and left. All checks to the left indicate that the two blues squares are free but the lower square contains a wall (black square). movement left is blocked. Movement vertically is free. So willy moves upward. . . Middle block diagram: Part 2: willy at this point is cell aligned and still moving upward and left. The orange squares are checked and found to be free. Willy is moved left and upward into the squares. . The arc of his flight moves onward till we arrive at picture 3 Right block diagram: Part 3: willy is cell aligned and wants to move left and downward. The question here is are the cells/squares in green free to move into. The answer being yes. Willy should be moved across the cell boundary into the green squares. . But in part 3 JSW has a specific check, that affects the outcome:- Willy is falling and the code (listed) below checks for what is beneath his feet. Even though at this point willy will not actually enter both of the squares that are checked below his feet. Willy is moving diagonally downward, and he moves both vertically and horizontally across cell boundaries. The check below does not move horizontally across the cell boundary and checks directly beneath Willies feet. (this is a bug) . *** Note the problem is due to incorrect horizontal cell checking. . This incorrect cell check, stops the jump and Willy lands on the wall. . The complete Jet Set Willy RAM disassembly 20171113
-
The room jump routines -- about 40 bytes shorter ROOM_L EQU $80E9 ROOM_R EQU $80EA ROOM_U EQU $80EB ROOM_D EQU $80EC CURRENT_ROOM EQU $8420 WILLY_Y EQU $85CF AIRBORNE EQU $85D1 ;ANIMATION EQU $85D2 WILLY_ATT EQU $85D3 WILLY_ATT_H EQU $85D4 NEW_ROOM EQU $8912 ;---------------------------------------------- GO_ROOM_LEFT: ;L948A LD BC,$FE1E ;;; OR LD BC $E01E LD HL,ROOM_L GO_NEW_ROOM: LD A,(HL) LD (CURRENT_ROOM),A LD HL,WILLY_ATT LD A,(HL) AND B OR C LD (HL),A ;L85D3 POP HL ; JP NEW_ROOM ;L8912 GO_ROOM_RIGHT: ;L949E LD BC,$E000 LD HL,ROOM_R JR GO_NEW_ROOM GO_ROOM_UP: ;L94B0 LD BC,$1FA0 LD HL,ROOM_U LD DE,$D05D XOR A VERT_PROCESS: LD (AIRBORNE),A LD A,E LD (WILLY_ATT_H),A LD A,D LD (WILLY_Y),A JR GO_NEW_ROOM GO_ROOM_DOWN ;L94D2 LD BC,$1F00 LD HL,ROOM_D LD DE,$005C LD A,(AIRBORNE) CP $0B JR NC,VERT_PROCESS LD A,$02 JR VERT_PROCESS Slight edit to set up variables in a more consistent manner.
-
Remake of Manic Miner- Both bug byte and S.P. versions
Norman Sword replied to Norman Sword's topic in Remakes
The visual differences between the bug byte version and Software projects version in room data The changed data consists of around 240 bytes changed. in 12 separate groups. Ranging from a single byte to a group of 127. Some of the data that changes may or may not be visual. But the program stores the around 480 bytes and swaps the 240 over on each playing. This is on top of the 2*256 bytes for the scrolling message. So Nearly 1k stored for the changes. The room data was left intact, and in the same format. I did consider adding a few more versions and the compressing the lot. -
Posted elsewhere on this forum, just moving into the download category as well. This version of Manic Miner contains both the Software projects version of the game alongside the Bug byte version. Each time the game is played it will swap versions. I have edited and revised a lot of the routines. The game should play the same way as the original game. A lot of the changes would need you to be aware of the originals exact format to enable comparisons. Cheat is enabled (bug-byte password) differences that I can remember 1) demo cycle stops and redisplayed the title screen and replays the title music 2) added a credits screen 3) added explosions on credit screen 4) added intermission screen 5) change scroll to pixel scroll and not character scroll 6) will moves with a sprite mask 7) explosion on death 8) willies death stump scrolls onto the screen 9) score scrolls to high score 10) reason given for demise 11) sound effects on solar ray 12) collection sound 13) cheat modes rebuild platforms 14) cheat mode immunity 15) cheat mode move by a single key, and not multi combinations of keys 16) cheat mode plays with all sprites active 17) game swaps between two versions- Bug Byte and software Projects 18) other sound effects 19) less sprite flicker 20) game runs faster 21) multiple icon displays 22) bar graph on title screen 23) Animated version icon on title screen 24) keyboard layout on title screen fixed 24a) title screen. missing pixel on car replaced 25) new screen scrolls 26) easter egg on Credit screen 27) easter egg on Pause 28) skylab landing sound effect 29) skylab does not colour in platforms etc... KEYS standard movement keys e.g. "q" to "p" for left to right "z" to "m" jump" "a" to "g" pause "h to "enter" music on/off The "1" key changes the method of movement. In cheat mode. the boot will still be displayed various icons are active and indicate options selected The "9" key rebuilds platforms the "3" key activates platform rebuild option (tool kit) the "4" key activates immortality (medical kit) The "9" key held plus Tapping "1" will move to a previous screen. If on room 1 then it will go to room 20 The "9" key held plus tapping "2" will move to the next screen. If on room 20 then it will go to room 1 Bug byte cheat is 6031769 Icons displayed are from right to left Paused Alternate movement Music on Cheat invoked medical kit tool kit BB-SP.tap
-
Just a note on the file I posted: What is happening? In the original JSW, the code for jumping and moving up and down ramps, are set in one overall routine that detects wall blocks and stops movement. Within the code of the original, was two sets of movement code that treated the movement going left and the movement going right differently. Moving left. The code for moving left omitted a check for head height blocks. This permits willies head to pass through blocks moving left. This also permits willies head to pass through blocks at head height when jumping. Another routine at #8df7 detects the passage through the block at head height and immediately pushes willy downward to cell align him into/onto the block below. In most cases this works well if willy is going upwards on a jump. If willy is going downwards on a jumping arc, then the code at #8df7 will appear to move willy suddenly downward. This is the characteristic jerk as willy hits a wall and slides down it into a gap. Moving right This code blocks the movement of willies head through a wall tile. The result is that willy can not jump into slots cut out of walls in the same manner. Because willies body and head do not enter in a wall tile, willy will slide down walls at a normal speed, until his feet land on something. consequence. The slight difference in the movement is why the game has cut outs in vertical walls only in left jumped to walls. The same style cut out that exist in right cut out walls normally have a platform below the cut out, on which willy can land. It also is the reason for the jerk jumping left in certain circumstances that are not replicated going right. Fixs Various fixs can be applied and each fix might cure one or other problem. 1) stop willies head passing through a block. This fix will stop the jumps into cut outs. 2) allow willies head to pass through a block going right. This fix will enable jumps left and right into cut outs. But willy will pass through so many blocks it just looks wrong. 3) rewrite the lot. This introduces so many new variables, that anything can happen. My thoughts on that are GOOD LUCK. DEMO The demo program posted above changes its set of rules depending on what is happening. 1) If willy is walking up or down a ramp then it will check for willies head/body/above head(going up)/below head (going down). When jumping the rules are changed. When jumping upward it checks above his head, his head and also his body. If not cell aligned it will check the third cell (lower body/under foot) 2) When jumping downward it ignores the head check and checks for his body and if free to move also checks the cell below his body (under foot). This double check for body and lower body/under foot is needed to ensure that willy is actually passing into a gap in which he can fit. (two cells high) If the two cells are free then the code permits willies head to pass through a wall block. The code at #8df7 will detect the passage through a wall block and immediately pull willy downwards into the gap. This is what happens in the original game. The only difference in this demo is that it now happens going left or right, but willies head is blocked from passing into wall blocks when walking, walking on ramps, or even jumping upward. Any modification will invariably introduce new problems. Simply because the original game appears to have been constructed around the non symmetry of code. Some of these problems are very easy to fix others are waiting to come to light. ADDENDUM Most of the labels I have in this area have been moved/change/deleted . I have had to use an unchanged version, to find the address I am referencing. Over head wall check, that push's willy downward , as written by The complete Jet Set Willy RAM disassembly 2017 11 13
-
Meanwhile :- something I wrote last week. ------ Which is an extension of my test files Not meant to be complete or working game. Just a test extension of matt's logic. Which also had tile blocking incorporated. The very jerky jumps, means the jumps happen a lot quicker than the nice smooth arcs of what the jumps should have been. Since the source code for this contains so many obsolete routines. It will probably be soon deleted/purged. jerky set wibble .tap
-
A viewpoint (which might change) based on code written today. The previous code and several other bits that modify the path that willy can take still have problems. I wrote a routine that shows in real time what tiles are being checked by this program. (allowing frame by frame analysis). What this routine showed was, that the checking has flaws in its design. The original routine was not symmetrical, and it was the non symmetry that allowed for jumping into gaps in walls. (In jsw all the gaps are accessed by jumping left) If symmetry is introduced then those gap jumps become impossible. But the other problems become more noticeable. Passing through a wall In the code that checks for ramps and also checks for blocking the move left and right, was a check for reducing the three cell check to only two, when willy was cell aligned. The primary reason was when willy walks along a platform, the third cell was below his feet. Since he was walking along the top of the cells, they could not block his path. Hence the third cell check is removed for that reason. (otherwise willy can not walk along a wall) However when willy is jumping the third cell is crucial for deciding if willy can move. g00a h00b kcde In the text diagram above willy occupies the four squares with "0" in them, in this case willy is jumping right and is on his way down. The two squares with "a" and "b" are clear. Since willy in this thought experiment is now cell aligned. The present routine has decided that "e" can be ignored. This then permits willy to move diagonally downward to the right to now occupy the cell "e". This is why the jump right on the "FIRST LANDING" passes through a square and lands inside the floor when jumping the gap on the lower floor. If I add a check for falling into the routine that checks for wall blocking when moving. The purpose of which is solely to force the third cell check when falling. Then this particular problem disappears. However it still permits passing though a wall block in "on top of the house" when walking down a stair (because those blocks are NOT checked by the stair check routine) Symmetry The third cell check stops one problem. But Symmetry causes a problem when jumping into gaps. Again looking at the text diagram, the cell "g" was not tested moving left, and that permitted walking through cells at head height. The cell "a" was tested when walking right. It is the lack of cell testing that permits jumping into wall gaps, when jumping left. The symmetrical code I posted will not permit jumping into two cell wide gaps in specific conditions because of the extra check. The jump left in "ball room east" into the gap above the red barrel can no longer be done. The reason is because the checking now stop movement into wall tiles. The gap was only two cells wide only when cell aligned. This does not happen when jumping from a horizontal position (which is level with the gap), because the forward motion has ceased at the exact point that the cells are aligned. From my viewpoint the non symmetry was deliberate, and in looking at the way the code is written, it is possible the change in logic from left and right was a quirk that was exploited I however prefer these anomalies to be written out of the code. Whatever it does one way should be the same the other way. Back to the cell checking.. Introducing a specific check for jumping (downward) to force a third square check, stops the movement into wall cells on jumping downward. It also appears that stopping the check for willies head when jumping and moving downward either left or right. Re-enables the passage into gaps. Removing the check for willies head (cell "g" or cell "a") but forcing the check for the third tile, means that willy can move into a two cell wide gap. In practical terms this is similar to permitting passage through the corner of a wall cell on his way down, only if the two cells below are not occupied by a wall. This Matthew style FIX permits a one frame movement into the gap. I have not had a good look at the code to implement these changes, in a manner that I am happy with. I have however added two additional pieces of code to implement these changes, which seem to do as I want. Which is symmetry in movement. 1) checking head height cell and blocking willy from moving through them ... *NOTE 1 2) ability to still jump into gaps 3) stop passage into wall cells *Note 1 The upper Platform in "the Forgotten Abbey" if left as a wall will block Willy walking of the conveyor underneath it.
-
If you wish to write a better version, please feel free to do so. My code is simply illustrating a path that can be taken.
-
Seeing the Ramp code this morning I realised that the subroutine it called was no longer needed. So I have rewritten the code and saved another seven bytes.
-
slight edit to change a comment, which was from code that no longer exists. The comment confused what was happening when testing for extremes of movement left and right. This code has been edited repeatedly to arrive at what is seen Comments are sometimes the remains of multiple copies, and pastes If I am aware of a misplaced comment, I will delete it or edit it. ;set variables for these offsets ramp_frame equ 0 ramp_animation equ 1*2 ramp_where_1 equ 2*2 ramp_where_2 equ 3*2 ramp_condition equ 4*2 ramp_adjust equ 5*2 ramp_exit_screen equ 6*2 ramp_final_adjust equ 7*2 ramp_animation_reset equ 8*2 ;left data followed by right data left_data db 0, 3 ;0 VALUE TO JUMP FRAME - limit of animation movement at same position DB -1, 1 ;1 STEP TO NEXT animation FRAME - replaces inc or dec DB $1f, $22 ;2 POSITION OF RAMP 1 - ramp walk up DB $41, $40 ;3 POSITION OF RAMP 2 - ramp walk down DB 0, 1 ;4 CONDITION FOR RAMP DIRECTION - decision to check for up or down DB -1, 2 ;5 DIRECTION TO ADJUST HL - where to check vertically DB 31, 0 ;6 CONDITION TO TEST FOR NEW ROOM (limit of travel) DB 0, -1 ;7 STEP BACK - adjust of hl after vert check DB 3, 0 ;8 ANIMATION RESET for next frame ;----------------------------------- . L8FBC: LD A,(ROPE_STATUS) ;L85D6 DEC A BIT 7,A RET Z LD A,(L85D0) BIT 1,A RET Z ; Willy now needs to move left or right ; this movement needs to handle the stairs and check for their presence ; decide if moving left or right ld ix,left_data AND $01 JR nz,skippp inc ix ;switch to right data skippp: ; Willy is moving LD HL,(WILLY_ATT) ;L85D3 LD DE,WILLY_ANM ;L85D2 LD A,(DE) cp (ix+ramp_frame) JR Z,RAMP_CHK add a,(ix+ramp_animation) LD (de),a ;L85D2 RET RAMP_CHK: ; all de increments are positive so preload D ld d,0 LD A,(AIRBORNE) ;L85D1 OR A JR NZ,as_is ; three outcomes going up bc=-32 ; going down bc=+32 ; no ramp bc=0 ld bc,-32 ld e,(ix+ramp_where_1) ld a,(RAMP_DIR) ;either 0 or 1 and 1 ;get rid of other bits cp (ix+ramp_condition) ; the sign test ; this condition swaps on left and right jr z,down_ ld bc,+32 ld e,(ix+ramp_where_2) down_: add hl,de ; add offset to find ramp/stair square ld a,(RAMP) sub (HL) jr z,found_ ;if ramp is here keep bc=shift ;ramp not found so no offset needed as_is: ld b,d ld c,d ;bc=0 no ramp so no offset/shift found_: ld hl,(WILLY_ATT) ; this test is for extremes of position when moving left or right LD A,L ;left edge =0 right edge=30 ADD A,(IX+ramp_adjust) ;move in the direction left or right LD L,A ;left edge =-1 right edge=32 AND 31 ;left edge=31 right edge=0 ; if value is zero then move right ld de,GO_ROOM_LEFT jr nz,exit_other_way ld de,GO_ROOM_RIGHT exit_other_way: CP (IX+ramp_exit_screen) ; have we moved to the extremes? JR NZ,same_room ;we have moved far enough to enter a new room ex de,hl jp (hl) ;now check a vertical line for walls blocking path same_room: ; just move vertically and check the squares ; this code only checks for WALL's nothing else ; after the initial add hl,bc this checks downwards in a line ; the initial adjust is for ramps. e.g. up/down or level ADD HL,BC ;Point HL at the cell at ; ;(y-1) Willy is on or about to go up a ramp ; ;(y+0) just walking ; ;(y+1) Willy is walking down a ramp ld a,(WALL) ;in theory this position could be off the top of the screen bit 1,h jr nz,ignore_head_check cp (hl) ;head ret z ;return if path is blocked ignore_head_check: ; now check vertically down LD DE,$0020 ADD HL,DE ;point hil at the cell one lower ; ;(y+0) Willy is on or about to go up a ramp ; ;(y+1) just walking ; ;(y+2) if Willy is walking down a ramp CP (HL) ;foot RET Z LD B,A LD A,(WILLY_Y) ;L85CF SRA C ADD A,C LD C,A AND $0F ;jumping JR Z,ONLY_TWO LD A,b ADD HL,DE ; check- maybe needlessly- but check anyway. BIT 1,H JR NZ,OFFSCREEN ; ;(y+1) Willy is on or about to go up a ramp ; ;(y+2) just walking ; ;(y+3) Willy is walking down a ramp CP (HL) ;beneath? RET Z OFFSCREEN: OR A SBC HL,DE ; move back to feet ; final adjust back to HL=head position ONLY_TWO: OR A SBC HL,DE ; back to head position (free to move here) ;Adjust HL back LD A,L ADD A,(IX+ramp_final_adjust) LD L,A LD A,(IX+ramp_animation_reset) ; the animation frame :save state: LD (WILLY_ANM),A ;L85D2 LD (WILLY_ATT),HL ;L85D3 LD A,C LD (WILLY_Y),A ;L85CF RET
-
I decided to ditch the whole of Matthews code for dealing with ramps. That is the code from $8fbc to $90b5 =$105= 259decimal In essence the code repeats for left and right. I wanted it to be exactly symmetrical, with no deviation in how it handles left or right. So the code I use handles both directions by having one routine, which has variables passed to it. The testing is the same in both directions and it is around 187 bytes in length or around 72 bytes shorter than Matthews version. The code in the post below has been edited to move the subroutine to inline code. This has reduced its size by 7 bytes. So length is now around 180 bytes or around 79 bytes shorter than Mattthews version.
-
Space saving The code from $8aab to $8ac6 8AAB LD BC,$FEFE Read keys SHIFT-Z-X-C-V 8AAE IN A,© 8AB0 LD E,A Save the result in E 8AB1 LD B,$7F Read keys B-N-M-SS-SPACE 8AB3 IN A,© 8AB5 OR E Combine the results 8AB6 AND $01 Are SHIFT and SPACE being pressed? 8AB8 JP Z,$87CA If so, quit the game 8ABB LD A,($85E0) Increment the inactivity timer at 85E0 8ABE INC A 8ABF LD ($85E0),A 8AC2 JR Z,$8AD1 Jump if the inactivity timer is now 0 (no keys have been pressed for a while) 8AC4 LD B,$FD Read keys A-S-D-F-G The code from 8AAB to 8ac6 can be replaced by CALL $1F54 JP NC,$87CA LD HL,$85E0 INC (HL) JR Z,$8AD1 ; c has not been set up yet, so the next instruction sets c LD BC,$FDFE ; ; ;in all the versions of Manic miner or JSW I have posted, I tend to not use BC for the ports Tendency is ld a,port_? ;port_? is assigned to the row or even multiple row of keys that will be read in a,($fe) The code I actually use is defined in a MACRO, so I will type and see Read_Port port_a+port_k ; this sets up and scans both keyboard rows. e.g. row a-s-d-f-g and row h-j-k-l-enter The reason I do this is to ensure the port is fully assigned when addressed. It also frees the BC register pair