Norman Sword Posted November 28, 2018 Report Share Posted November 28, 2018 (edited) Modification of Manic miner tune. The above routine was an exercise in compacting the code. Code that was never used. The original modification from. SUB 8RRCA RRCA RRCA CPL OR #E0 TO RRCA RRCA RRCA NEG OR #E0 --- my code has OR L where L=#e0 This modification works fine and gives exactly the correct results. And does not need any additional code.my error was just swapping the routine around, whilst still thinking about the CPL instruction used in the first routine NEGRRCARRCARRCAOR #E0 --- my code has OR L where L=#e0Moving the NEG from after the RRCA instructions to before the RRCA instruction changed what it did.Simpler to revert back to the sequenceSUB 8CPL RRCA RRCA RRCA AND 31OR L Since the above code has been tested. I know it works for all values, in exactly the same way as the original. Works 100%The routine is still 70 plus bytes smaller than the original. Addendum. The AND 31 instruction was added before the code change to compacted data. The reason for its inclusion was to permit the moving of the piano graphics to any screen line, and not be forced via the old code to one of 3 fixed screen positions. 2nd addendum:The code I reference is the original layout. Unfortunately for me, I have edited so much code and done so many changes in the code, that I would need to keep going backward and forward checking items for reference.The code listed in the Manic Miner music routine, is a derivative of the original code, which because of dual usage no longer OR's in the screen address, It now adds it. This slight change is what the next post #12 is referring to as the difference in opcode usage. The code I listed is relocatable and not fixed to any memory address. In the context of being placed back into Manic Miner, it can again have the restrictions imposed on it. The tune data and the two data tables used for data expansion, can be fixed into a page, along with the fixed screen keyboard reference. This can remove several opcodes and make it even smaller. (something I will not do). I prefer the options of being able to have code where ever I place it Edited November 28, 2018 by Norman Sword Spider, jetsetdanny and IRF 3 Quote Link to comment Share on other sites More sharing options...
IRF Posted November 28, 2018 Author Report Share Posted November 28, 2018 (edited) my code has OR L where L=#e0 Isn't it ADD A, L (to facilitate the multiple use of the subroutine, which is also used for decompressing the tune data)? Edited November 28, 2018 by IRF Quote Link to comment Share on other sites More sharing options...
IRF Posted November 29, 2018 Author Report Share Posted November 29, 2018 The code I listed is relocatable and not fixed to any memory address. In the context of being placed back into Manic Miner, it can again have the restrictions imposed on it. The tune data and the two data tables used for data expansion, can be fixed into a page, along with the fixed screen keyboard reference. This can remove several opcodes and make it even smaller. (something I will not do). I prefer the options of being able to have code where ever I place it You previously mentioned the trade-off between size versus speed when optimising code. The above quote highlights a third element to throw into the balance - flexibility (relocatability). Spider and jetsetdanny 2 Quote Link to comment Share on other sites More sharing options...
IRF Posted December 11, 2018 Author Report Share Posted December 11, 2018 (edited) 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. I've been playing around with the MM title tune routine, and I've managed fix the 'glitch' mentioned above. If the routine encounters a 'zero note', then that note is now bypassed. i.e. no piano key is highlighted, but also no corresponding note is played. This also allows you to have 'pure tones' in the title tune. (In the original MM, attempting to play a pair of notes with identical pitch values causes no note at all to be played for the allocated duration of that pair of notes. So when a 'single note' is played - as opposed to a chord of two notes of different pitch - this is achieved by assigning values to a pair of notes that differ by 1. e.g. #846F and #8470 hold #80 and #81 respectively. The slight difference in pitch gives a 'harpsichord' quality to such notes.) In the attached test file, there is a mixture of pure tones (where the original tune data held a pair of notes differing by 1, one of the note bytes now holds a zero value, whilst the other note is unchanged (e.g. the first note pair at #846F and #8470 hold values #80 and #00) and 'chords' (all pairs of notes in the original tune data that differed significantly from each other have been left with their original values. e.g. the last pair of notes in the tune #8589 and #858A hold values #80 and #CB, as per the original MM). And of course the 'silent note' near the end of the tune (#8541 and #8542 both hold zero values) no longer illuminates the left-most (or indeed any) of the piano keys. The resulting tune sounds smoother and less harsh. (Although admittedly the harshness in the original adds to the 'manic' quality, in keeping with the theme of the game: 'Manic Miner'. So this test file was created purely for experimental purposes, and to further my own knowledge of how this particular tune-playing routine operates.) MANIC Title Tune 0 Smoother.TAP Edited December 12, 2018 by IRF Spider 1 Quote Link to comment Share on other sites More sharing options...
Spider Posted December 11, 2018 Report Share Posted December 11, 2018 Does sound quite uniquely different. :) It does make the 'harsh' tones stand out more though but that's expected (not a negative thing) just they are more apparent now. IRF 1 Quote Link to comment Share on other sites More sharing options...
IRF Posted December 11, 2018 Author Report Share Posted December 11, 2018 (edited) In theory, on those occasions when two notes are played simultaneously, they are two notes in a harmonic series, so they aren't actually 'harsh' as such (compared with playing two notes which are slightly different in pitch to each other, which can sound quite disharmonic especially at higher pitches). EDIT: That's the theory anyway! All the pair of notes in the original definitely sound harsher than they do if you separate each half of the pair out and play them separately (by NOPping out one or other of the two XOR #18 commands from the title tune routine). Edited December 13, 2018 by IRF Spider 1 Quote Link to comment Share on other sites More sharing options...
IRF Posted December 12, 2018 Author Report Share Posted December 12, 2018 (edited) A few posts back, I uploaded an experimental file ('File 0') in which the MM title tune routine and data had been modified, so that pairs of notes which were previously close in value (differing by 1) now play a pure tone, giving the tune a 'smoother' quality than in the original game. (This was achieved by replacing one of each near-matching notes with the value zero, and then hacking the title tune routine so that such 'zero notes' get bypassed instead of being played.) I then thought I would see what would happen if I experimented with the reverse approach. I have attached a selection of further test files to this post: For comparison, I have attached 'File 1' which is a copy of the original Manic Miner with no changes to the game file except that it has been renamed for consistency with the sequence that follows. The '1' refers to the fact that many of the pairs of notes are assigned pitch values which differ by #01. In 'File 2', those notes which previously differed by #01 are separated in pitch by a difference of #02. In 'File 3', the 'close note pairs' differ by a value of #04; 'File 4' by #08, and in 'File 5' the pairs of notes which originally almost matched each other in pitch now differ by #10 (16 in decimal). So the 'close notes' are spread apart by increasingly large amounts as you progress through the files - I hope that makes sense? For example, in 'File 5' the values stored at addresses #846F and #8470 (the first pair of notes in the title tune) are #80 and #90, instead of #80 and #81 at those same addresses in the original game. The net result is that the quality of the tune sounds increasingly harsher and more dischordant as you work your way through the files, which are thus named accordingly. Er, enjoy! MANIC Title Tune 1 Original.TAP MANIC Title Tune 2 Harsher.TAP MANIC Title Tune 3 Even Harsher.TAP MANIC Title Tune 4 Extremely Harsh.TAP MANIC Title Tune 5 Silly.TAP Edited December 13, 2018 by IRF Spider 1 Quote Link to comment Share on other sites More sharing options...
IRF Posted December 17, 2018 Author Report Share Posted December 17, 2018 Number 5 is aptly named! Spider 1 Quote Link to comment Share on other sites More sharing options...
Spider Posted December 17, 2018 Report Share Posted December 17, 2018 Number 5 is aptly named! Indeed! :D IRF 1 Quote Link to comment Share on other sites More sharing options...
Norman Sword Posted January 19, 2019 Report Share Posted January 19, 2019 (edited) ; MANIC MINER PIANO ROUTINE for the ZX spectrum ; The only reason for this updated routine is the change in lighting the keyboard on silent notes; if two notes are defined, and with the same values the keyboard will still light up. For silence use 0,0 ;the complete title music routine for Manic Minermanic_tune: LD DE,L33902 ; music datamanic_loop:; is the music finished LD A,(DE) ; length and pitch shift OR A ; terminate on zero RET Z; else find out the note length AND 3 ; a third bit is available if needed LD HL,TIME_SHIFT CALL STEP_INDEX LD C,A ; NOTE LENGTH; and extract the pitch shift LD A,(DE) ; THE note shift INDEX LD HL,NOTE_SHIFT CALL STEP1_INDEX LD B,A ; THE NOTE SHIFT INC DE; extract the first note and light keyboard LD A,(DE) ; (NOTE 1) INC DE PUSH DE ; the data pointer saved - we want to use the registers LD D,A ; (NOTE 1);This must calculate at least one value for HL CALL NOTE_PLACE ; we want HL the pointer PUSH HL;calculate 2nd NOTE LD A,D ; NOTE 1 ADD A,B ; NOTE 1+NOTE SHIFT = NOTE 2 LD E,A ; NOTE 2; here we light the keyboard only if this NOTE HAS A VALUE INC D DEC D JR Z,same_notes1 LD (HL),PAPER2+BRIGHT ;#50 ; press the key #50=(PAPER RED +BRIGHT)same_notes1: CALL NOTE_PLACE ; returns HL PUSH HL; same as above, only light if this has a value DEC E INC E JR Z,same_notes2 LD (HL),PAPER5 ; PAPER5=40=$28 PAPER5=(PAPER CYAN)same_notes2: LD B,0 ; initialise b LD A,L ; the border is set from L; XOR A ; an alternative to the line above, force no border flash LD L,E ; NOTE 2 (LOWS) LD H,D ; NOTE 1 (HIGHS) ;what's what now;E = L - NOTE 2 (low registers);D = H - NOTE 1 (high registers);BC = - overall duration ; note B=0 length is in "C";A = last piano keyboard position and this dictates the border colour tune_loop: OUT (#FE), A ; note 1 (HIGH REGS) DEC D JR NZ,tl_1 LD D,H XOR #18tl_1: DEC E ; note 2 (LOW REGS) JR NZ,tl_2 LD E,L XOR #18tl_2: DJNZ tune_loop DEC C JR NZ, tune_loop; noise completed, erase the pressed keys POP HL LD (HL),PWHITE ; PWHITE=56=$38 ; the default keyboard colour 56=$38=(paper white + ink black) POP HL LD (HL),PWHITE ; PWHITE=56=$38 ;; restore the data pointer POP DE ; restore the note pointer;check for exit and then loop CALL test_enter ;#9337 ; Check whether ENTER or the fire button is being pressed RET NZ JR manic_loop ATT15 equ $59e0 ; The attribute position of the piano, which is defined as line 15 ; calculate the screen position to press a key based on "a" the noteNOTE_PLACE: LD HL,ATT15 ; this address is free to move up or down the screen SUB 8 CPLSTEP1_INDEX: RRCA RRCASTEP2_INDEX: ;used by the delay routine RRCA AND 31STEP_INDEX: ADD A,L LD L,A ADC A,H SUB L LD H,A LD A,(HL) RET ;: Title screen tune data (The Blue Danube); The tune data is organised into 95 groups of two bytes; two bytes of data for each dual note played.; The first byte is split into two values.;; byte 1 ------xxb the xxb value is an index into the TIME_SHIFT array. This supplies the note duration.; byte 1 xxxxx---b the xxxxxxb value is an index into the NOTE_SHIFT array. this supplies the shift from the first note to the second note; byte 1 -----x--b the xb value is unused in this data;; byte 2 xxxxxxxxb the xxxxxxxxb value is raw data and is the value of the first pair of music notes. This value is identical to the middle; value in the original 3 byte layout. It is the NOTE value for NOTE 1;; The value extracted from the NOTE_SHIFT array is simply added to the value of NOTE 1; the sum of NOTE 1 and the NOTE_SHIFT value is the value for NOTE 2 TIME_SHIFT:; 0 1 2 3 ; notice I have used 75 (which is the logical value to use) DB 25, 50, 75, 100 NOTE_SHIFT: ; 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 DB 0, 1, 6, 8, 10, 11, 13, 20, 21, 24, 32, 43, 75, 77, 128, 154 ; L33902:DB 2+8*1,128DB 2+8*1,102DB 2+8*1,86DB 1+8*1,86DB 1+8*10,171DB 1+8*3,43DB 1+8*3,43DB 1+8*10,51DB 1+8*6,64DB 1+8*6,64DB 1+8*10,171DB 1+8*1,128DB 1+8*1,128DB 1+8*1,102DB 1+8*1,86DB 1+8*4,86DB 1+8*8,171DB 1+8*4,43DB 1+8*4,43DB 1+8*8,171DB 1+8*7,48 DB 1+8*7,48 DB 1+8*8,171DB 1+8*1,136DB 1+8*1,136DB 1+8*1,114DB 1+8*1,76DB 1+8*1,76 DB 1+8*8,171DB 1+8*8,38DB 1+8*8,38 DB 1+8*8,171DB 1+8*7,48 DB 1+8*7,48 DB 1+8*8,171DB 1+8*1,136DB 1+8*1,136DB 1+8*1,114DB 1+8*1,76 DB 1+8*1,76DB 1+8*10,171DB 1+8*6,38DB 1+8*6,38 DB 1+8*10,171DB 1+8*6,51DB 1+8*6,51DB 1+8*10,171DB 1+8*1,128DB 1+8*1,128DB 1+8*1,102DB 1+8*1,86 DB 1+8*1,64 DB 1+8*11,128DB 1+8*5,32DB 1+8*5,32DB 1+8*11,128DB 1+8*3,43DB 1+8*3,43DB 1+8*11,128DB 1+8*1,128DB 1+8*1,128DB 1+8*1,102DB 1+8*1,86 DB 1+8*1,64 DB 1+8*9,128DB 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,114DB 1+8*1,114DB 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,86DB 1+8*15,51 DB 1+8*1,51 DB 1+8*1,51DB 1+8*15,51DB 1+8*1,64 DB 1+8*1,102DB 1+8*1,102DB 3+8*1,114DB 1+8*1,76 DB 1+8*1,86 DB 1+8*12,128DB 0+8*14,128 DB 0+8*1,128DB 1+8*12,128 DB 0 ;End marker Edited January 19, 2019 by Norman Sword jetsetdanny, IRF and Spider 3 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.