Context In short, the water surface object (obj1B) is a necessity for covering up artifacts which occur as a result of the mid-screen color swapping which creates the water’s transparent effect.* Sonic 3 incorporates an alternative method in which it only copies three colors per line which keeps most artifacts off screen, removing the necessity of the water surface object. This gives the water a more natural, less cartoony look and prevents sprite flicker when several sprites are on the same horizontal lines as the water’s surface. In addition, if chosen well enough, the method of changing three colors per line can give a sense of depth to the water’s surface. *Most emulators don’t recreate the artifacts found on real hardware. The ones that I know of that do are Exodus and BlastEm. The screenshots I’ve taken are from BlastEm. Part 1: Remove obj1B These lines in “Level_ChkWater” spawn the object and set its initial state, so just delete them or comment them out. Code: cmpi.b #1,($FFFFFE10).w ; is level LZ? bne.s Level_LoadObj ; if not, branch move.b #$1B,($FFFFD780).w ; load water surface object move.w #$60,($FFFFD788).w move.b #$1B,($FFFFD7C0).w move.w #$120,($FFFFD7C8).w Part 2: Replacing PalToCRAM PalToCRAM is the code Sonic 1 calls during a horizontal interrupt, which happens during every HBlank, which is the period between the drawing of scanlines. It is here where the game switches colors to create the water effect, but it can also be used to switch out information in order to make 2 player possible or adjust the VSRAM (Vertical Scrolling RAM) to create vertical scaling effects. Here, it mainly just changes the CRAM (Color RAM) to the water palette at the correct spot. Replace everything from “PalToCRAM:” to before “locret_119C” with this code taken from Sonic 3: Code: PalToCRAM: tst.w ($FFFFF644).w beq.s locret_119C move.w #0,($FFFFF644).w movem.l d0-d1/a0-a2,-(sp) lea ($C00000).l,a1 move.w #$8ADF,4(a1) ; Reset HInt timing move.w #$100,($A11100).l ; stop the Z80 @z80loop: btst #0,($A11100).l bne.s @z80loop ; loop until it says it's stopped movea.l ($FFFFF610).w,a2 moveq #$F,d0 ; adjust to push artifacts off screen @loop: dbf d0,@loop ; waste a few cycles here move.w (a2)+,d1 move.b ($FFFFFE07).w,d0 subi.b #200,d0 ; is H-int occuring below line 200? bcs.s @transferColors ; if it is, branch sub.b d0,d1 bcs.s @skipTransfer @transferColors: move.w (a2)+,d0 lea ($FFFFFA80).w,a0 adda.w d0,a0 addi.w #$C000,d0 swap d0 move.l d0,4(a1) ; write to CRAM at appropriate address move.l (a0)+,(a1) ; transfer two colors move.w (a0)+,(a1) ; transfer the third color nop nop moveq #$24,d0 @wasteSomeCycles: dbf d0,@wasteSomeCycles dbf d1,@transferColors ; repeat for number of colors @skipTransfer: move.w #0,($A11100).l ; start the Z80 movem.l (sp)+,d0-d1/a0-a2 tst.b ($FFFFF64F).w bne.s loc_119E $FFFFF610 is an unused longword variable in Sonic 1, but any mentioning of this variable can be replaced with any free longword variable. The same goes for $FFFFFE07, which is byte length. This code will read a table pointed to by $FFFFF610 and write to CRAM the 3 consecutive colors the table points to that corresponds with the scanline the interrupt is at at that moment. $FFFFFE07 is a replacement for $FFFFF625, which is the position of the water's surface on screen. Read MarkeyJester's post to understand why $FFFFF625 is inaccurate to what is represented on screen. To update $FFFFFE07, at loc_C22, loc_CD4, loc ED8, and loc_F9A, underneath "move.w ($FFFFF624).w,(a5)", add this line: Code: move.b ($FFFFF625).w,($FFFFFE07).w Part 3: Creating The Table In “Level_ClrVars3”, underneath the line “bne.s Level_LoadPal”, add this: Code: move.l #WaterTransition_LZ,($FFFFF610).w Finally, the table can be created. Here is an example which works fairly well with Labyrinth Zone. I recommend putting it before LZWaterEffects. Code: WaterTransition_LZ: dc.w $13 ; # of entries - 1 dc.w $62 dc.w $68 dc.w $7A dc.w $6E dc.w $74 dc.w $42 dc.w $48 dc.w $4E dc.w $54 dc.w $5A dc.w 2 dc.w 8 dc.w $E dc.w $14 dc.w $1A dc.w $34 dc.w $22 dc.w $3A dc.w $2E dc.w $28 The first entry of the table is the header, which is the number entries after it minus 1. The value of each entry corresponds to a location in “pallet/lz_uw.bin” and is the first of six consecutive bytes that will be written to CRAM during its corresponding horizontal interrupt. The first entry is read on the same line that is generally used as the surface of the water, and each subsequent entry is read on the next line underneath. This table in particular will switch every color color except the background color at $40. Part 4: Taking Advantage of the Effect That’s it for coding, but here is part where you can get creative with it. If you look at Angel Island Zone, which uses this technique, the location at which each set of colors is loaded at is chosen carefully so that things which can be interpreted as being the closest to the camera have their water colors switched at lower scanlines than things that are more towards the back, creating a sense of depth. In fact, at first I thought this was intentional and not a workaround for the limitations of the console. This works nicely because darker shades often represent areas further away because shadows tend to form in those areas. In Labyrinth Zone, the indented parts of the face tiles are darker, creating this effect. Of course, there are places where this is not the case and the illusion can falter, such as how some thin pillars have priority over Sonic, yet are covered by a higher level of water than Sonic. Fortunately, the effect is subtle enough that a few inconsistencies won’t ruin it. Generally, I recommend loading background colors first, then the foreground colors, then the colors of Sonic and other objects you’d find near the surface, and finally anything that you would rarely see near the surface, such as colors used by the enemies. Any colors that remain unchanged in the water can be left off the table. If you want to go above and beyond to ensure the best effect, then you can arrange the palette so that every three colors that must be on the same line are together and loaded at the same time, you can reload the same background colors before loading the rest of the colors so that the background looks more distant, you can reload two old colors and one new color several times so that each darker shade even further away, or you can draw your level art with this effect in mind by using colors in groups of three, only putting shadows in areas that should be further away, and reserving colors specifically for things that are further away. Part 5: Bugs There are two bugs I've found: W̶h̶e̶n̶ ̶t̶h̶e̶ ̶s̶c̶r̶e̶e̶n̶ ̶s̶w̶i̶t̶c̶h̶e̶s̶ ̶f̶r̶o̶m̶ ̶m̶a̶i̶n̶l̶y̶ ̶u̶s̶i̶n̶g̶ ̶t̶h̶e̶ ̶n̶o̶r̶m̶a̶l̶ ̶p̶a̶l̶e̶t̶t̶e̶ ̶t̶o̶ ̶t̶h̶e̶ ̶u̶n̶d̶e̶r̶w̶a̶t̶e̶r̶ ̶p̶a̶l̶e̶t̶t̶e̶,̶ ̶t̶h̶e̶ ̶n̶o̶r̶m̶a̶l̶ ̶p̶a̶l̶e̶t̶t̶e̶ ̶s̶t̶a̶y̶s̶ ̶f̶o̶r̶ ̶a̶ ̶f̶r̶a̶m̶e̶ ̶l̶o̶n̶g̶e̶r̶ ̶t̶h̶a̶n̶ ̶i̶t̶ ̶s̶h̶o̶u̶l̶d̶,̶ ̶r̶e̶s̶u̶l̶t̶i̶n̶g̶ ̶i̶n̶ ̶a̶ ̶f̶l̶a̶s̶h̶.̶ ̶I̶ ̶h̶a̶v̶e̶ ̶s̶p̶e̶n̶t̶ ̶h̶o̶u̶r̶s̶ ̶c̶o̶m̶p̶a̶r̶i̶n̶g̶ ̶c̶o̶d̶e̶ ̶a̶n̶d̶ ̶c̶o̶u̶l̶d̶ ̶n̶o̶t̶ ̶f̶i̶n̶d̶ ̶a̶ ̶s̶o̶l̶u̶t̶i̶o̶n̶ ̶t̶o̶ ̶w̶h̶y̶ ̶t̶h̶i̶s̶ ̶h̶a̶p̶p̶e̶n̶s̶ ̶i̶n̶ ̶S̶o̶n̶i̶c̶ ̶1̶,̶ ̶b̶u̶t̶ ̶n̶o̶t̶ ̶S̶o̶n̶i̶c̶ ̶3̶K̶.̶ ̶I̶ ̶s̶u̶s̶p̶e̶c̶t̶ ̶t̶h̶a̶t̶ ̶t̶h̶e̶r̶e̶ ̶i̶s̶ ̶s̶o̶m̶e̶ ̶d̶e̶l̶a̶y̶ ̶i̶n̶ ̶t̶h̶e̶ ̶c̶o̶d̶e̶ ̶t̶h̶a̶t̶ ̶w̶r̶i̶t̶e̶s̶ ̶t̶o̶ ̶C̶R̶A̶M̶ ̶o̶r̶ ̶t̶h̶e̶ ̶e̶v̶e̶n̶t̶s̶ ̶l̶e̶a̶d̶i̶n̶g̶ ̶u̶p̶ ̶t̶o̶ ̶w̶r̶i̶t̶i̶n̶g̶ ̶t̶h̶e̶ ̶u̶n̶d̶e̶r̶w̶a̶t̶e̶r̶ ̶p̶a̶l̶e̶t̶t̶e̶ ̶t̶o̶ ̶C̶R̶A̶M̶ ̶a̶r̶e̶ ̶h̶a̶p̶p̶e̶n̶i̶n̶g̶ ̶o̶u̶t̶ ̶o̶f̶ ̶o̶r̶d̶e̶r̶.̶ ̶I̶’̶d̶ ̶a̶p̶p̶r̶e̶c̶i̶a̶t̶e̶ ̶a̶n̶y̶ ̶h̶e̶l̶p̶ ̶w̶i̶t̶h̶ ̶f̶i̶g̶u̶r̶i̶n̶g̶ ̶t̶h̶i̶s̶ ̶o̶u̶t̶.̶ Because there is no scanline above the top scanline of the screen, the game switches from using the normal palette to using the underwater palette once the surface of the water goes above the top of the screen. The scanlines underneath which have a mix of normal and underwater colors will turn to their underwater colors, which can be jarring to look at. As far as I can tell, Sonic 3K has that same issue, but manages to keep most things that would most noticeably change color close enough to the water’s surface so that it isn’t noticeable. I recommend doing the same.