diff --git a/README.md b/README.md
index b63ab78..b58d56b 100644
--- a/README.md
+++ b/README.md
@@ -1,7 +1,7 @@
 # Raspberry Casket
 A fast and small open source Pretracker replayer
 
-## Raspberry Casket Player V1.0 (26-Dec-2022)
+## Raspberry Casket Player V1.1 (28-Dec-2022)
 
 Provided by Chris 'platon42' Hodges <chrisly@platon42.de>
 
@@ -83,12 +83,15 @@ The original code compressed with *Blueberry's* Shrinkler goes from
 18052 bytes down to 9023 bytes.
 
 Raspberry Casket, depending on the features compiled in, is about
-6374 bytes and goes down to ~4410 bytes (in isolation).
+6216 bytes and goes down to ~4348 bytes (in isolation).
 
 So this means that the optimization is not just "on the outside".
 
 ### Timing
 
+Sample generation is a bit faster (I guess around 10-15%), but most of the time is spent on muls operations, so this is the limiting factor.
+Raspberry Casket is about twice as fast as the old replayer for playback.
+
 Unfortunately, the replayer is still pretty slow and has high
 jitter compared to other standard music replayers.
 
@@ -103,24 +106,30 @@ solve this problem.
 ### Known issues
 
 - Behaviour for undefined volume slides with both up- and down nibble specified is different (e.g. A9A, hi Rapture!). Don't do that.
-- Don't use loops with odd lengths and offsets.
+- Don't use loops with odd lengths and offsets (even if Pretracker allows this when dragging the loop points).
 - Don't stop the music with F00 and use a note delay (EDx) in the same line.
 - Don't try to play music with no waves, instruments or patterns.
-- Shinobi seemed to have used an early beta version of Pretracker where it was possible to specify a Subloop Wait of 0. That's illegal.
+- Pattern breaks with target row >= $7f will be ignored.
+- Shinobi seemed to have used an early beta version of Pretracker where it was possible to specify a Subloop Wait of 0. That's illegal and unsupported.
+- Pattern break (Dxx) + Song pos (Bxx) on the same line does not work in original Pretracker & Player: New Dxx position is ignored. 
+  There is code to enable it in the player, so you could in theory make backwards running tracks like in Protracker. 
+  But this doesn't make sense as long as the tracker itself does not support it.
 
 ## Changelog
 
-### V1.1 (unreleased)
-- Optimized base displacement by reordering variables
-- Further optimized ADSR code
-- Optimized wave loop code
-- Bake in this strange vibrato speed multiplication to precalculated vibrato value (where possible)
-- Various small optimizations
-- Store instrument number * 4 on loading to avoid using two adds every frame
+### V1.1 (28-Dec-22)
+- Optimized base displacement by reordering variables.
+- Further optimized ADSR code.
+- Optimized wave loop code.
+- Bake in this strange vibrato speed multiplication to precalculated vibrato value (where possible).
+- Various small optimizations.
+- Store instrument number * 4 on loading to avoid using two adds every frame.
 - Optimized speed/shuffle code. Idea of using xor turned out to make things too complicated for pattern breaks/jumps.
 - Rearranged code for more short branches.
 - Optimized track delay code further.
-- Drop-in replacement code size: 6304 bytes.
+- Optimized pattern / song advance code.
+- Maximum jitter now about one rasterline less, average about 0.5 rasterlines less (measurements, your mileage may vary).
+- Drop-in replacement code size: 6228 bytes.
 
 ### V1.0 (26-Dec-22)
  
diff --git a/binaries/raspberry_casket.bin b/binaries/raspberry_casket.bin
index 25808b1..2f641c2 100644
Binary files a/binaries/raspberry_casket.bin and b/binaries/raspberry_casket.bin differ
diff --git a/binaries/readme.txt b/binaries/readme.txt
index cfc7dc3..6ae6124 100644
--- a/binaries/readme.txt
+++ b/binaries/readme.txt
@@ -1,5 +1,5 @@
 This file "raspberry_casket.bin" can replace the original "player.bin"
 provided that you used the 16 KB + 16 KB allocation for player
-variables as in the original player.
+variables as in the original player (you need only about 2 + 12 KB).
 
-It has been assembled from src/drop_in_replacement.asm (version V1.0).
\ No newline at end of file
+It has been assembled from src/drop_in_replacement.asm (version V1.1).
\ No newline at end of file
diff --git a/example/plastic_duff.exe b/example/plastic_duff.exe
index 5e0e469..d3dd32c 100644
Binary files a/example/plastic_duff.exe and b/example/plastic_duff.exe differ
diff --git a/example/readme.txt b/example/readme.txt
index b3abecd..06cde5f 100644
--- a/example/readme.txt
+++ b/example/readme.txt
@@ -3,7 +3,7 @@ It features Pink's song Plastic Dove (from the Coda Intro).
 
 Even though it features the full replayer code and tune,
 the replayer including my demo framework and the song only
-takes a mere 6560 bytes (shrinkled), which is even smaller
+takes a mere 6448 bytes (shrinkled), which is even smaller
 than the new streaming replayer used in Pink's new streaming
 player demonstrated (closed source) in
 
@@ -11,7 +11,7 @@ https://www.pouet.net/prod.php?which=91551
 
 which is 6860 bytes.
 
-The Raspberry Casket replayer takes an average of 14
+The Raspberry Casket replayer takes an average of 13.5
 rasterlines while Pink's new streaming player takes
 only about 10 rasterlines.
 
diff --git a/src/raspberry_casket.asm b/src/raspberry_casket.asm
index 92f389f..4fb8a77 100755
--- a/src/raspberry_casket.asm
+++ b/src/raspberry_casket.asm
@@ -1,6 +1,6 @@
 ;--------------------------------------------------------------------
-; Raspberry Casket Player V1.1beta (28-Dec-2022)
-; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+; Raspberry Casket Player V1.1 (28-Dec-2022)
+; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 ;
 ; Provided by Chris 'platon42' Hodges <chrisly@platon42.de>
 ;
@@ -87,15 +87,22 @@
 ; 18052 bytes down to 9023 bytes.
 ;
 ; Raspberry Casket, depending on the features compiled in, is about
-; 6374 bytes and goes down to ~4410 bytes (in isolation).
+; 6216 bytes and goes down to ~4348 bytes (in isolation).
 ;
 ; So this means that the optimization is not just "on the outside".
 ;
 ; Timing
 ; ~~~~~~
+; Sample generation is a bit faster (I guess around 10-15%), but most
+; of the time is spent on muls operations, so this is the limiting
+; factor.
+;
+; Raspberry Casket is about twice as fast as the old replayer for
+; playback.
+;
 ; Unfortunately, the replayer is still pretty slow and has high
 ; jitter compared to other standard music replayers.
-; This means it may take up to 33 raster lines (14-19 on average)
+; This means it may take up to 32 raster lines (13-18 on average)
 ; which is significant more than a standard Protracker replayer
 ; (the original one could take about 60 raster lines worst case and
 ; about 34 on average!).
@@ -639,7 +646,7 @@ pre_FuncTable
         dc.l     pre_PlayerInit-pre_FuncTable
         dc.l     pre_PlayerTick-pre_FuncTable
         ENDC
-        ;dc.b     '$VER: Raspberry Casket 1.0',0
+        ;dc.b     '$VER: Raspberry Casket 1.1',0
         ;even
 
         IFNE    PRETRACKER_COPPER_OUTPUT
@@ -2906,29 +2913,66 @@ pre_PlayerTick:
 ; end of pattern loop
 
 ; ----------------------------------------
-; pattern advancing FIXME try to figure out all the cases
+; Pattern advancing and pattern break and jump handling. Song looping and song-end detection.
 .pattern_advancing
         subq.b  #1,pv_pat_line_ticks_b(a4)
         bne     .no_pattern_advance
 
         ; clear note delay info
-        moveq.l #0,d1
+        moveq.l #0,d0
         REPT    NUM_CHANNELS
-        move.b  d1,pv_channeldata+pcd_note_delay_b+REPTN*pcd_SIZEOF(a4)
+        move.b  d0,pv_channeldata+pcd_note_delay_b+REPTN*pcd_SIZEOF(a4)
         ENDR
 
-        move.b  sv_num_steps_b(a6),d1
-        subq.b  #1,d1
-        move.b  pv_next_pat_row_b(a4),d0
-        blt.s   .no_pattern_break
-        cmp.b   d0,d1
-        bgt.s   .has_legal_break_pos
-        move.b  d1,d0                       ; limit to last step
-.has_legal_break_pos
-        move.b  d0,pv_pat_curr_row_b(a4)
+        move.b  sv_num_steps_b(a6),d1       ; number of steps in pattern
 
-        move.w  sv_curr_pat_pos_w(a6),d3    ; go to next pattern pos
-        addq.w  #1,d3
+        move.b  pv_pat_curr_row_b(a4),d0
+        addq.b  #1,d0                       ; normal step increment
+
+        move.w  sv_curr_pat_pos_w(a6),d3    ; current song position
+
+        move.b  pv_next_pat_row_b(a4),d2    ; $ff means no pattern break
+        bmi.s   .no_pattern_break
+        st      pv_next_pat_row_b(a4)       ; processed break, set to $ff
+        move.b  d2,d0
+        IFNE    0 ; PRETRACKER_BUGFIX_CODE  ; currently disabled to keep old behaviour
+        moveq.l #0,d2                       ; clear mask
+        ENDC
+        cmp.b   d1,d0
+        blo.s   .has_legal_break_pos
+        move.b  d1,d0                       ; limit to last step
+        subq.b  #1,d0
+        bra.s   .has_legal_break_pos
+
+.no_pattern_break
+        cmp.b   d1,d0
+        blo.s   .pattern_end_not_reached
+        moveq.l #0,d0
+        IFNE    PRETRACKER_PARANOIA_MODE
+        move.b  pv_loop_pattern_b(a4),d0    ; keep same pattern rolling?
+        bne.s   .pattern_end_not_reached
+        ENDC
+.has_legal_break_pos
+        addq.w  #1,d3                       ; pattern break will increment song pos -- if there is no new pattern position
+
+.pattern_end_not_reached
+        move.b  pv_next_pat_pos_b(a4),d4
+        bmi.s   .no_new_position            ; has a new pattern position
+        st      pv_next_pat_pos_b(a4)
+        IFNE    PRETRACKER_SONG_END_DETECTION
+        cmp.b   d4,d3
+        bgt.s   .no_backjump
+        st      pv_songend_detected_b(a4)   ; detect jumping back
+.no_backjump
+        ENDC
+        move.b  d4,d3                       ; load new position
+        IFNE    0 ; PRETRACKER_BUGFIX_CODE  ; currently disabled to keep old behaviour
+        not.b   d2
+        and.b   d2,d0                       ; if we had NO pattern break, we will clear d0
+        ELSE
+        moveq.l #0,d0
+        ENDC
+.no_new_position
 
         cmp.w   sv_pat_pos_len_w(a6),d3
         blt.s   .no_restart_song
@@ -2937,87 +2981,15 @@ pre_PlayerTick:
         st      pv_songend_detected_b(a4)
         ENDC
 .no_restart_song
-        move.w  d3,sv_curr_pat_pos_w(a6)
-
-        st      pv_next_pat_row_b(a4)       ; processed break, set to $ff
-
-        move.b  pv_next_pat_pos_b(a4),d3
-        bge.s   .has_new_position           ; has a new pattern position together with a break
-        move.b  d0,d2                       ; backup pv_pat_curr_row_b
-        cmp.b   d0,d1
-        ble.s   .end_of_pattern_reached
-        bra.s   .done_pat_advance
-
-.no_pattern_break
-        move.b  pv_next_pat_pos_b(a4),d3
-        bge.s   .has_new_position
-        move.b  pv_pat_curr_row_b(a4),d0
-        move.b  d0,d2
-        cmp.b   d1,d2
-        blt.s   .advancetonextpos
-
-.end_of_pattern_reached
-        clr.b   pv_pat_curr_row_b(a4)
-        IFNE    PRETRACKER_PARANOIA_MODE
-        move.b  pv_loop_pattern_b(a4),d0    ; keep same pattern rolling?
-        bne     .done_pat_advance
-        ENDC
-        bra.s   .advance_song_pos
-
-.advancetonextpos
-        addq.b  #1,d2
-        move.b  sv_num_steps_b(a6),d1
-        addq.b  #1,d0
-        cmp.b   d2,d1
-        bgt.s   .dont_go_to_top_row
-        moveq.l #0,d0
-.dont_go_to_top_row
         move.b  d0,pv_pat_curr_row_b(a4)
-        bra.s   .done_pat_advance
-
-.has_new_position
-        clr.b   pv_pat_curr_row_b(a4)
-        IFNE    PRETRACKER_PARANOIA_MODE
-        move.b  pv_loop_pattern_b(a4),d0
-        bne     .no_restart_song_after_jump
-        ENDC
-
-        cmp.w   sv_pat_pos_len_w(a6),d3
-        blt.s   .set_song_pos2
-        move.w  sv_pat_restart_pos_w(a6),d3
-        IFNE    PRETRACKER_SONG_END_DETECTION
-        st      pv_songend_detected_b(a4)
-        ENDC
-.set_song_pos2
         move.w  d3,sv_curr_pat_pos_w(a6)
-        ; enters with d0 = 0
-.no_restart_song_after_jump
-        st      pv_next_pat_pos_b(a4)       ; processed jump, set to $ff
 
-        subq.b  #1,d2
-        bhi.s   .done_pat_advance
-        clr.b   pv_pat_curr_row_b(a4)
-        tst.b   d0
-        bne.s   .done_pat_advance
-
-.advance_song_pos
-        move.w  sv_curr_pat_pos_w(a6),d0
-        addq.w  #1,d0
-        cmp.w   sv_pat_pos_len_w(a6),d0
-        blt.s   .set_song_pos
-        move.w  sv_pat_restart_pos_w(a6),d0
-        IFNE    PRETRACKER_SONG_END_DETECTION
-        st      pv_songend_detected_b(a4)
-        ENDC
-.set_song_pos
-        move.w  d0,sv_curr_pat_pos_w(a6)
-.done_pat_advance
-        move.b  pv_pat_speed_even_b(a4),d0
-        btst    #0,pv_pat_curr_row_b(a4)
-        beq.s   .set_speed_even
-        move.b  pv_pat_speed_odd_b(a4),d0
+        move.b  pv_pat_speed_even_b(a4),d1
+        lsr.b   #1,d0
+        bcc.s   .set_speed_even
+        move.b  pv_pat_speed_odd_b(a4),d1
 .set_speed_even
-        move.b  d0,pv_pat_line_ticks_b(a4)
+        move.b  d1,pv_pat_line_ticks_b(a4)
 .no_pattern_advance
 
 ; ----------------------------------------