For those interested in how the patch works, and how I went about figuring it all out, here's a copy of a post I made recently to the BBC Micro mailing list...
----------------------------------------------------------
We load the executable &2000 bytes higher than its load address to allow room for that Basic loader. All the code at lines 110-160 is concerned with is relocating the executable down to the right place (quickly) and running it.
Line 60:
These poke new colours into the palette used by the game.
We deduce that the palette is stored at &2B7D from the following code in the game:
Code: Select all
2B5B: LDX #&0F ; start at index 15
2B5D: STX &88
2B5F: LDX &88 ; loop start: get index
2B61: STX &2B78 ; store colour index
2B64: LDA &2B7D,X ; lookup physical colour
2B67: STA &2B79 ; store physical colour
2B6A: LDX #&76
2B6C: LDY #&2B
2B6E: JSR &1A26 ; print string pointed to by &YYXX
2B71: DEC &88 ; dec loop index
2B73: BPL &2B5F ; re-loop
2B75: RTS
2B76: <06> ; length of string to print
2B77: <13> ; VDU 19
2B78: <00> ; poked with colour index
2B79: <00> ; poked with physical colour
2B7A: <00> <00> <00>
As standard, the game makes special use of the following colours:
0 black (background)
1 yellow (eggs + lift)
2 magenta (grain + ladders + score)
3 green (platforms)
4 yellow (you + big bird+cage)
8 cyan (enemy birds)
The other palette entries echo these colours in appropriate ways. Since all sprites are EORed on the screen, other colours will arise, e.g. when a cyan bird climbs a ladder, we will get pixels in colour (8 EOR 2)=10. Hence the game sets colour 10 to cyan so we don't notice these artifacts (birds appear in front of ladders).
Now, it turns out that eggs have an independent palette entry (colour 1) to the main character and the big bird. This is so the big bird doesn't overprint eggs and leave a black egg-shaped hole (4 EOR 4 = 0). But this means we can trivially set this palette entry to colour 7 instead of 3 (?&4B7E=7). Voila, white eggs.
It also turns out there's an overprint which is never possible - cyan birds over green platforms (I think this is true anyway?). This corresponds to colour 11 (8 EOR 3), so we'll define this as red (?&4B88=1) and print our status sprites in this new colour.
Line 70:
This is a cosmetic change. We have changed colour 1 to white from yellow.
The main title 'CHUCKIE EGG' is printed in colour 1, so in order to make sure it stays in yellow, we now explicitly change its print colour to colour 4 (which is still yellow). Here's where this appears in the executable:
Code: Select all
2CE5: LDA #&02 ; select physical colour 1 (PATCHED)
2CE7: STA &7F ; store in 'colour' variable used by sprite plotter
2CE9: LDA #&30 ; select sprite &30 ('C' in 'CHUCKIE EGG')
2CEB: LDX #&02 ; X position 2
2CED: LDY #&F0 ; Y position &F0 (0=bottom, &FF=top)
2CEF: JSR &2DBE ; plot sprite
2DBE is a generic routine which takes a colour in ?&7F, a sprite number in A, and coordinates in X,Y, and draws a sprite. By changing LDA#&02 to LDA#&20, we plot the sprite in colour 4. (The value used is the one which would set the leftmost pixel of the byte to the desired colour in MODE 2).
Line 80:
these are involved with changing the colour the status sprites ('score', 'level', 'time', 'player', 'bonus') are printed in, from magenta (colour 2) to red (colour 11). In each case, there is code setting ?&7F to 8 (colour 2: magenta). We just want to change it to 138 (colour 11: red). ?&3CC4=138 deals with the 'score' sprite:
Code: Select all
1CC3: LDA #&08 ; select colour 2 (PATCHED)
1CC5: STA &7F
1CC7: LDX #&00
1CC9: LDY #&F8
1CCB: JSR &1987 ; set up screen address from X/Y
1CCE: LDA #&29 ; select sprite 'SCORE'
1CD0: JSR &19DB ; set up sprite address in A
1CD3: JSR &1902 ; print sprite (screen+sprite addrs
; must already be set up)
?&3D01=138 deals with the other status sprites:
Code: Select all
1D00: LDA #&08 ; (PATCHED)
1D02: STA &7F
1D04: LDX #&00
1D06: LDY #&E8
1D08: JSR &1987
etc
Line 90:
This pokes a routine which appears to print the score for the first time. We want white scores, so we need to overprint the red background in colour (11 (red) EOR 1 (white)) = 10. This corresponds to a screen byte value of 136. This does mean that scores not on a red background (i.e. other players') will appear cyan (colour 10), but hey-ho, it's all a bit of extra colour isn't it?
Lines 20-40, 100, 110:
This is all to do with plotting digits. We already know that we need to print them in colour 10. The game used to plot them in colour 2 (which, overprinted on a background of colour 2 yields colour 0 - black). In these cases, colour 2 is already set up, so these pokes patch the call to the sprite routine (JSR &1902) and replace it with a call to my own assembler routine in lines 20-40:
Code: Select all
; generic number printing code (A = digit to print)
1B01: PHA ; save A
1B02: JSR &1987 ; set up scrn address from X/Y
1B05: PLA ; restore A
1B06: CLC
1B07: ADC #&1F ; add 31 (digits are sprites 31-40)
1B09: JSR &19DB ; set up sprite address in A
1B0C: JSR &1902 ; print sprite (PATCHED)
1B0F: RTS
; print player number
1D1A: LDA &5D ; player number
1D1C: CLC
1D1D: ADC #&20 ; digit 1 base
1D1F: JSR &19DB ; set up sprite address in A
1D22: JSR &1902 ; print sprite (PATCHED)
My assembler routine just saves the colour at ?&7F, sets it to colour 10, calls the original routine, and then restores the old value of ?&7F. This seems to work very nicely because Chuckie Egg never touches the memory at &380..&3E0, so we're free to fill it with any patch code we need.