Jump to content
Jet Set Willy & Manic Miner Community

Free space and code optimisation in Manic Miner


IRF

Recommended Posts

I thought I might create a similar 'optimisation' thread to the JSW one.

 

I implemented a lot of code optimisations of the MM game engine in the recent release 'Manic Mixup'.  However, this one slipped through the next (I've only just thought of it):

 

It involves a rewrite of the routine at #92DC which plays the theme tune (Blue Danube).  I think this saves around 12 bytes.  EDIT: It actually saves eight bytes.  (I forgot to count the CALL to test the Enter key, and the RET back to the Title Screen routine if Enter is pressed.)

 

start:

       LD A, (IY+$00)

       INC A

       RET Z

       LD BC, #5028

       CALL update_piano_keys

       LD B, #00

       LD C, (IY+$00)

       LD H, D

       LD L, E

tune_loop:

       OUT (#FE), A

       DEC D

       JR NZ, not_time_for_note_1

       LD D, H

       XOR #18

not_time_for_note_1:

       DEC E

       JR NZ, not_time_for_note_2

       LD E, L

       XOR #18

not_time_for_note_2:

       DJNZ tune_loop

       DEC C

       JR NZ, tune_loop

       LD BC, #3838

       CALL update_piano_keys

       CALL #9337                            Check whether ENTER or the fire button is being pressed

       RET NZ

       LD DE,#0003

       ADD IY, DE

       JR start

 

update_piano_keys:

       LD A, (IY+$01)

       LD D, A

       CALL #932B

       LD (HL), B

       LD A, (IY+$02)

       LD E, A

       CALL #932B

       LD (HL), C

       RET

Edited by IRF
Link to comment
Share on other sites

This doesn't relate to code optimisation, but it's an observation about a bug/glitch/peculiarity in the original Manic Miner.

 

When the title screen tune is playing, there is a pause towards the end (enacted by having a pair of 'zero notes', at #8541 and #8542).  You might expect that none of the piano keys are highlighted at that point, since no notes are being played, but in fact the left-most key of the piano is highlighted (in cyan).

 

I know that the positioning of the coloured keys isn't actually representative of the notes that would be played on a real piano, but the above seems particularly incongruous.

Edited by IRF
Link to comment
Share on other sites

If the zero's are changed to any other value you can move the illuminated note up to any position, as long as they both stay the same value, you will still have silence. Which does not change the fact that the keyboard illuminates. 

Since the design of the keyboard looks like it was constructed from several broken ones. Lets just assume that the far left key is not working, and when struck the keyboard makes no noise. 

Edited by Norman Sword
Link to comment
Share on other sites

My original edit of this from around six months ago is only 12 bytes shorter than the post #0

I admit I have had numerous attempts at shrinking the code, in most case the end result  stayed about the same size. So those numerous attempts where deleted months ago.

I did however try one more time to edit this routine, and I did save a few bytes. My final edit for the overall Manic Miner Music routine is around 57 bytes smaller than the Music routine from post #0

 

I did however try one more time to edit this routine, and I did save a few bytes. My final edit for the overall Manic Miner Music routine is around 57 bytes smaller than the overall Music routine from post #0

So you know it can be done.


Addendum

The music routine consists of two parts. The code to play the music and the music data. One without the other serve no purpose in the game. 

Edited by Norman Sword
Link to comment
Share on other sites

It did strike me that there's still some repetition of code in my rewrite - the use of D and then E as pitch delay counters for the two notes could possibly utilise a shared subroutine, if the registers were swapped about carefully?

 

Oh, I presume that there's a comma missing in the last post: "My final edit for the overall Manic Miner Music routine is around 57 bytes smaller than the Music routine from post #0" should read "My final edit for the overall Manic Miner Music routine is around 57 bytes, smaller than the Music routine from post #0" - unless you've managed to compress the routine down to 14 bytes in length! :o

Edited by IRF
Link to comment
Share on other sites

Edited and swapped some registers around - another 2+ bytes smaller

 

This code can be placed anywhere in ram.

 

;The complete title music routine (data and code) for Manic Miner

;
Manic_Miner_Title_Music:
        ld de,Tune_Data
;
manic_loop:
        ld a,(de) 
        OR A          
        RET Z
        AND 3              
        LD HL,TIME_SHIFT
        CALL STEP_INDEX  

        LD C,A                                << added   
        LD (S_M_C_ahead),A
        LD A,(DE)
        LD HL,NOTE_SHIFT
        CALL STEP1_INDEX

        LD B,A                               << added
        LD C,A
        INC DE
        LD A,(DE) 
        inc de
        push de
        ld d,a   ;NOTE 1            
        CALL NOTE_PLACE
        push hl
        ld (hl),#50
        ld a,d

        add a,b                             << added        
        add a,c 
        ld e,a  :NOTE 2           
        call NOTE_PLACE  
        push    hl
        ld (hl),#28
        LD A,L 
        ld l,e  ;NOTE 2   (lows)  
        ld h,d ;NOTE 1 (highs)

        ld b,0                              <<added
S_M_C_ahead: equ $+1
        ld      bc,0   

tune_loop:
        OUT (#FE), A 
        DEC D   :NOTE 1 (highs)                  
        JR NZ,tl_1  
        LD D,H                
        XOR #18                 
tl_1:
        DEC E : NOTE 2 (lows)                   
        JR NZ,tl_2  
        LD E,L                  
        XOR #18                 
tl_2:
        DJNZ tune_loop          
        DEC C                   
        JR NZ, tune_loop        
        POP HL             
        LD (HL),56
        POP HL             
        LD (HL),56
       POP DE
        CALL test_enter ;#9337
        RET NZ               
        JR manic_loop          

;
NOTE_PLACE:
        LD HL,#59e0       ; with this code, the piano address can be at the start of any attribute line
        SUB 8      
        CPL 
STEP1_INDEX
        RRCA
        RRCA
        RRCA
        and 31
STEP_INDEX:
        ADD A,L
        LD L,A
        ADC A,H
        SUB L
        LD H,A
        LD A,(HL)
        RET

;
TIME_SHIFT: DB 25,50,80,100
NOTE_SHIFT: DB  0, 1, 6, 8, 10, 11, 13, 20, 21, 24, 32, 43, 75, 77, 128, 154
;
Tune_Data:  
DB 2+8*1,128
DB 2+8*1,102
DB 2+8*1,86
DB 1+8*1,86
DB 1+8*10,171
DB 1+8*3,43
DB 1+8*3,43
DB 1+8*10,51
DB 1+8*6,64
DB 1+8*6,64

DB 1+8*10,171
DB 1+8*1,128
DB 1+8*1,128
DB 1+8*1,102
DB 1+8*1,86
DB 1+8*4,86
DB 1+8*8,171
DB 1+8*4,43
DB 1+8*4,43
DB 1+8*8,171

DB 1+8*7,48
DB 1+8*7,48
DB 1+8*8,171
DB 1+8*1,136
DB 1+8*1,136
DB 1+8*1,114
DB 1+8*1,76
DB 1+8*1,76
DB 1+8*8,171
DB 1+8*8,38

DB 1+8*8,38
DB 1+8*8,171
DB 1+8*7,48
DB 1+8*7,48
DB 1+8*8,171
DB 1+8*1,136
DB 1+8*1,136
DB 1+8*1,114
DB 1+8*1,76
DB 1+8*1,76

DB 1+8*10,171
DB 1+8*6,38
DB 1+8*6,38
DB 1+8*10,171
DB 1+8*6,51
DB 1+8*6,51
DB 1+8*10,171
DB 1+8*1,128
DB 1+8*1,128
DB 1+8*1,102

DB 1+8*1,86
DB 1+8*1,64
DB 1+8*11,128
DB 1+8*5,32
DB 1+8*5,32
DB 1+8*11,128
DB 1+8*3,43
DB 1+8*3,43
DB 1+8*11,128
DB 1+8*1,128

DB  1+8*1,128
DB 1+8*1,102
DB 1+8*1,86
DB 1+8*1,64
DB 1+8*9,128
DB 1+8*2,32
DB 1+8*2,32
DB 1+8*9,128
DB 1+8*4,38
DB 1+8*4,38

DB 1+8*0,0
DB 1+8*1,114
DB 1+8*1,114
DB 1+8*1,96
DB 1+8*1,76
DB 1+8*13,76
DB 1+8*1,77
DB 1+8*1,77 
DB 1+8*13,76
DB 1+8*1,91

DB 1+8*1,86
DB 1+8*15,51
DB 1+8*1,51
DB 1+8*1,51
DB 1+8*15,51
DB 1+8*1,64
DB 1+8*1,102
DB 1+8*1,102
DB 3+8*1,114
DB 1+8*1,76

DB 1+8*1,86

DB 1+8*12,128
DB 0+8*14,128 
DB 0+8*1,128
DB 1+8*12,128

DB 0 ;

 

 

Addendum:-

 

slight change shortens code by 3 more bytes so around 73+ bytes smaller.
 

Edited by Norman Sword
Link to comment
Share on other sites

A most cunning rewrite, Norman!  Especially the shared subroutine for decompressing the data and determining which piano key gets highlighted!

 

I presume that this element (the bit in bold):

 

 


ADD A, L

LD L, A

ADC A,H
SUB A, L
LD H,A

LD A, (HL)

 

is there to take into account the possibility that the 'time shift' and 'note shift' look-up tables might be in a position which straddles two pages of memory?  That's a very useful technique; thanks for drawing my attention to it.

 

Incidentally, I believe that the following would achieve the same thing (in the same number of bytes):

 

    ADD A, L

    LD L, A

    JR NC, grab_data

    INC H

grab_data:

    LD A, (HL)

 

 

******

 

One subtle visual difference that your alternative code might produce - the pair of 'almost matching' notes at the start of the tune holds pitch values #80 and #81.  With the original code, playing that pair of 'almost matching' notes only illuminates a single piano key (in cyan).  With your version, I believe (without having tried it out yet) that two adjacent keys will be illuminated (one in red, one cyan).  This is because the two notes end up on opposite sides of an 'octal boundary'.  (Each piano key corresponds to an 'octet' of pitch values. i.e. for every increase in the pitch value of 8, we proceed from highlighting one piano key to the next).

 

That discrepancy could be resolved by tweaking the data (so that the corresponding pitch values are #7F and #80, and a similar consideration could be given for other values that are close to an 'octal boundary').  I don't believe that the perceived difference in pitch would be audible.

 

**

 

On the other hand, your code has the effect of fixing a little-known 'bug'* in the original game engine - namely that if you try to play a note of extremely high pitch (holding a value between #01 and #07), then the leftmost piano key gets highlighted, whereas you would expect the far right-hand piano key to be the one that is illuminated for such a high-pitched note.  (*It's a 'theoretical bug', because of course no note of that pitch manifests itself in the title tune data.)

 

The fix which I came up with for that is to replace the SUB A, #08 at #932B with a DEC A; I think your code will have the same effect in terms of determining when the transition from one highlighted key to another occurs.

 

(Your previous comment about "design of the keyboard [looking] like it was constructed from several broken ones" is also relevant here!)

Edited by IRF
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.