Introduction
============

These are notes from converting the Spectrum 48KB game "Mayhem" to the CPC.

The  original  game was written by the author Mark Incley when he was 15 years
old.  A  big  thankyou for his permission to convert it. Visit his website at:
http://www.inkland.org.uk/

See              the              Spectrum             version             at:
https://worldofspectrum.org/archive/software/games/mayhem-the-power-house

In  the  spirit  of  conversions  done  in  the day I will convert this to the
equivalent Amstrad model which is a 64KB CPC464.

I  spent  a little bit of time adjusting gameplay to compensate for the slower
frame rate on the CPC and to adjust some of the messaging all of this was code
related.  I  could have spend a lot more time polishing the graphics and audio
and  optimising  it but I chose not to as this was not always done back in the
day.

My  aim  is to produce a CPC version which would have been close to what could
have been done in the day with a 1 person team.

To  aid me I had partially commented source and data (made from a dissassembly
of the original game made by the author) which made the conversion much easier
to do. I didn't need to spent as much time dissassembling and working out what
the code did.
This  also  made  it  easier  for  me  to  change it for the CPC without being
concerned about having to find space to insert my changes.

From  the  information  here  you  can  understand  what  is involved, all the
details  (big  and small) of porting a game from Spectrum to CPC and how I did
it. This can then be related to the games back in the day and we can have some
better  understanding  of  why some companies took the easiest route and did a
simple Spectrum port, and why the Amstrad version was slower than the Spectrum
version.

I  never  liked  the  fast  made porting method which were slow so don't think
that  I  am  excusing  these  companies  by  making  this version. I did it to
understand why more.

One  thing is clear, without a musician and an artist it is harder to make the
best port!! I tried to make better graphics by myself and failed.

It is worth noting that my approach differs from back in the day:
- I am using a pc and modern development tools to do this.
- I  am  using  an  emulator and it's debugger which allows me to profile code
and to find bugs quicker.
- I have more time to invest - there is no deadline
- I don't need to concern myself with the money

Remember  the  details  below  apply to this game but can be related to others
and there are different challenges for converting scrolling games etc.



General Memory map
==================

Spectrum (48K system):

* 0000-3fff - 16KB system ROM - fixed - 16384 bytes
* 4000-57ff - Screen memory - fixed - (6144 bytes)
* 5800-5aff - Screen/attributes colour ram - fixed - (768 bytes)
* 5b00-5bff - printer buffer
* 5c00-5cbf - System variables
* 5cc0-5cca - reserved
* 5b00-ff57 - useable by programs.
* ff58-ffff - reserved

NOTES:
-  4000-7fff  is "contented" RAM, that is access to this ram is shared between
CPU  and  video  and  therefore  runs  "slower"  on  Spectrum (approx 3.3Mhz).
&8000-&FFFF  is uncontended RAM and is only accessed by the CPU so runs faster
(4Mhz)
-  Access  to  Spectrum's  contended  RAM  is almost equivalent to CPCs memory
access speed. Access to Spectrum's uncontended RAM is faster than on the CPC.
-  Access to the ULA port FE is also contended. Therefore reading keyboard and
Sinclair joysticks are contented. Access to ports for Kempston joystick is not
contented.
-  With Spectrum BASIC/OS running 5C00-5CBF are system variables and 5CC0-5CCA
are reserved.
-  However,  many  programs  use as much as possible including 5b00-ffff which
gives  them  42240 useable bytes. They often use IM2 which requires a 257 byte
table and a 3 byte JP instruction. This leaves 41980 bytes for code and data.

Amstrad (64KB system):

* 0000-0040 - lower firmware jumpblock
 NOTE: 0000-3fff is shared with system ROM which is paged in/out.
* 0040-a5ff - free for programs - 42431 bytes
* a600-bb00 - used by AMSDOS
* bb00-be00 - firmware jumpblock
* be00-bf00 - used by AMSDOS
* bf00-bfff - Stack
* c000-ffff - 16KB screen
 NOTE: C000-3fff is shared with BASIC ROM which is paged in/out.

NOTES:
*  Access  to  the  entire  0000-ffff  RAM  is  the  same  speed because it is
effectively  shared  between  CPU  and  video.  It is equivalent to the entire
Spectrum RAM being contended. Therefore the same code is going to run slightly
slower on the
CPC compared to Spectrum.
*  We  need  to  consider  that the program needs to be loaded into RAM either
from  tape  or  disc.  If  we are using firmware functions we need to restrict
ourselves to the free area and then copy code/data to it's final location.
If we are using custom loaders we don't have this restriction.
*  In  theory the entire CPC ram is available for use. We can disable the ROMS
and  never  page  them  in/out. We can run the CPC in interrupt mode 1. With a
standard  16KB screen and a 3 byte JP at interrupt mode 1 jump handler at 0038
we therefore have 49149 bytes free to use.

Mayhem's memory map
===================

Spectrum version:
- Doesn't use the OS
- Doesn't load more data
- uses the entire memory
- uses an IM2 interrupt
- 41980  bytes for code and data (screen and  attributes are fixed and already
subtracted from this number).

memory map in detail:

* 0000-3fff - 16KB system ROM - fixed - 16384 bytes
* 4000-57ff - Screen memory (6144 bytes)
* 5800-5aff - Screen/attributes colour ram (768 bytes)

* 5b00-5fff - 1279 bytes unused

* 6000-7fff - room data (in contended RAM)
* 8000 - code
* a7a7 - IM2 interrupt vector JP
* a7aa - unused (85 bytes)
* a800 - IM2 vector table (257 bytes filled with A7)
* a901 - stack (127 bytes)
* a980 - pickup tiles
* a9a8 - score tiles
* a9f8 - font (768 bytes)
* acf8 - bomb store
* ad88 - "sinclair, sinclad, amclair...amstrad"
* ae18 - torches on wall
* aea8 - droid servicer
* af38 - c64
* b010 - large picture
* b130 - android in prison
* b1c0 - ys
* b250 - in case of fire
* b328 - sunset painting
* b400 - tile attribites
* b500 - tile bitmaps
* bd00 - girl robots and "my hero"
* c100 - explosion sprites
* c300 - aerobomb sprites
* c500 - boss sprites
* c700 - enemy robot sprites
* db00 - player sprites
* e000-e7ff - HUD pixels (2048 bytes)
* e800-e8ff - HUD Attributes (256 bytes)
* e900 - scrolling instruction text
* ee00- backbuffer attributes
* f000- backbuffer

Amstrad version:
- Does use the standard OS tape and disc loader to load.
- Doesn't use the OS or BASIC during execution
- Doesn't load more data
- uses the entire memory
- uses an IM1 interrupt
- Uses a spectrum sized screen
- 65472 bytes for screens, code and data. (this doesn't include screens)

I use one Spectrum sized screen based at &8000 and another based at &c000.
The main continuous area of RAM is then 0040-7fff.

Mayhem's memory map (Amstrad):


* 0000-0038 unused (56 bytes)
* 0038-003a JP for interrupt mode 1
* 003a-003f unused (6 bytes)
* 0040-1721 Room data
* 1722-         Code
* 8000-85ff Screen 2
* 512 bytes unused
* 8800-8dff Screen 2
* 512 bytes unused
* 9000-95ff Screen 2
* 512 bytes unused
* 9800-9dff Screen 2
* 512 bytes unused
* a000-a5ff Screen 2
* a600-a77f - 384 - gfx_l1
* a780-a7ff - 128 bytes unused
* a800-adff Screen 2
* ae00-af7f - 384 - gfx_l2
* af80-afff - 128 bytes unused
* b000-b5ff Screen 2
* b600-b7ff - 512 bytes - explosion bitmaps
* b800-bdff Screen 2
* be00-bf7f - 384 bytes - gfx_b2
* bf80-bfff - 128 bytes - unused
* c000-c5ff Screen 1
* c600-c77f - 384 bytes - Screen table
* c780-c7ff - 128 bytes - Stack
* c800-cdff Screen 1
* ce00-ceff - 256 bytes - Mask table
* cf00-cfff - 256 bytes - tile ids for hud
* d000-d5ff Screen 1
* d600-d7ff - 512 bytes - aerobomb sprites
* d800-ddff Screen 1
* de00-dfff - 512 bytes - the boss bitmaps
* e000-e5ff Screen 1
* e600 e6ff - 256 bytes - gfx_s1
* e700-e7ff - 256 bytes - gfx_s2
* e800-edff Screen 1
* ee00-eeff - 512 bytes - gfx_b1
* f000-f5ff Screen 1
* f600-f6ff - 256 bytes - gfx_b3
* f700-f7ff - 256 bytes - gfx_b4
* f800-fdff Screen 1
* fe00-feff - 256 bytes - gfx_b5
* ff00-ffff - 256 bytes - gfx_b6

Continous vs non-continuous memory/data
=======================================

The  CPC  Mayhem  memory map has a number of smaller regions within the screen
RAM that can be re-used.

Code:

Code  is  easier.  When  code  is split into functions, each function is often
small enough to fit in, or large ones can be split and JP/JR instructions used
to go to the next part.

I didn't do this with CPC Mayhem.

Data:

Data from a "third party" - such as a music data may not be splitable.

Some  data  may  be split across multiple regions or individual blocks of data
can be put into space. This is what is used with CPC Mayhem.

In  addition  some  generated data (CPC screen address table, mask table) also
fit here.

To  maximize  the  usage and reduce waste the data needs to be organised well.
See the memory map for the usage.

Mode 0/Mode 1
=============

Mode  1  is  the  easiest  choice  as  the graphics can be converted as-is and
modified.
Mode  0  is  much  more colourful and would really require an artist because I
tried to make graphics and they didn't look good. I tried both converting mode
1 to mode 0 and colouring them and trying to make my own mode 0 graphics.

I  decided  on  mode  1  as it was easier but also when I tried to make mode 0
graphics I couldn't get enough definition in the graphics.

It was difficult to choose a nice palette to use with mode 1.

I    used    the   wonderful   'Musee'   from   'Les   Sucres   en   Morceaux'
(http://cpc.sylvestre.org/)  to help me to identify nice palettes to use. From
this I made a palette for the main menu and a palette per level.

I  wish  I could have used CPC interrupts and colour the hud separate from the
game area, however it's too tall and the natural position of the interrupts on
the  screen  didn't easily line up with the hud being at the top. I could have
chosen  to  change  colour  and  waste  some  CPU  cycles  to  change palettes
accurately  or move the screen up so I could take advantage of the position of
the  interrupts  in  relation  to  the  screen in it's changed position, but I
didn't want to loose any more CPU cycles and moving the screen up made it look
odd.

The  Spectrum version used a lot of colour to show state in the hud and in the
game.

I  looked  into  colouring  both background and sprites using all 4 colours in
the  palette  but  found it was difficult to identify the enemies, pickups etc
from  the  background, and while making the PCW version, I felt it was nice to
make  a  distinction.  Therefore the choice was made to adjust the sprites and
background  colours  so  that  the  background  is  darker and the sprites and
important graphics are brighter in comparison.

In  addition  some  of the graphics have been re-worked to make them less busy
so that they are easier to read.

Yes  this  means  fewer  colours but the screen I believe is easier to look at
and read.

Loader
======

For  the  cassette version I used the standard block loader. This is authentic
to the software house that would have released it on the CPC. It is a standard
1000  baud  loader,  where each block is 2K and each block has a pause between
it.

Back  in  the day there would not have been a disc version released, therefore
the disc version is 'unofficial' and is just a single bin file to run.

Room data
=========

All  rooms were aligned on 64 byte boundary but many used less data. The rooms
were already stored in a compressed form.

Optimisations (recommended by the author):
-  Removed  blank by packing together and changing compression so less data is
stored:  Was  8192  bytes  now 5850. Saving 2342 bytes. Now less than Spectrum
version.

Main Tiles:
===========

Spectrum:

* 1bpp
* 16x16.
* Each tile's pixels takes 32 bytes.
* 64 tiles.
* Attribute data for 64 tiles (2x2 attributes)

Total: (64*32)+(64*4) = 2304 bytes.

CPC:

* 2bpp
* 16x16.
* Each tile's pixels takes 64 bytes.
* 64 tiles.
* No attribute data

Total: (64*64) = 4096 bytes

Extra 1792 bytes compared to Spectrum.

No optimisations possible.

Sprites:
========

Spectrum:

* 1bpp
* 16x16.
* No attribute data
* Graphics 16x16 followed by mask 16x16.
* Each sprite takes 64 bytes.

CPC:

* 2bpp
* 16x16.
* Pen 0 used as mask.
* Each sprite takes 64 bytes.
* Mask table 256 bytes

Extra 256 bytes compared to Spectrum.

There  are  sprites  for  both  left and right. I could have stored a table to
reverse the graphics but I chose not to.

Collision
=========

If  choosing mode 0 for graphics we need to fix all the collision code because
there  are  less pixels horizontally. e.g. Where a tile is 16x16 in mode 1, it
will often be replaced with a tile 8x16.

This covers the same area on the monitor but the pixels are wider in mode 0.

I  therefore  went  through the assembler code replacing the numbers with equs
for  TILE_WIDTH_PIXELS,  TILE_HEIGHT_PIXELS  etc,  when investigating a mode 0
version.

When  using  mode  1  there is no need to change any of the collision code and
therefore a port using mode 1 is quicker to do.

Example collision types:
e.g.
Player->Map
Player->Enemy
Enemy->Map

Testing
=======

The  assembler  code  has lots of 'IF','ENDIF' constructs which can be enabled
for testing and are disabled in the released version.

In  this  way all the special rooms, game over, completion sequence etc can be
tested in isolation.

Adjustments to game
===================

Some  adjustments  were  made  to  gameplay  to make it a little bit easier to
understand  and  play. This is where I spent a little bit of time that back in
the day may not have been done for time reasons.

-  I allowed the player's bullets to destroy the boss enemy (The one with 'L')
because it was much harder to play if the bullet couldn't do that.

-  The  droid  servicer could only ever be used once but it wasn't clear after
you  had  used it if it was useable again. Now the Droid servicer is not drawn
when re-entering room after use.

-  The C64 could be destroyed over and over in a game. Now it can be destroyed
once per game.

-  Adjusted  time to 30 mins to give more chance to complete and since the CPC
version  seems  to  be  running a little slower than Spectrum. I would like to
have  changed time to 25 mins but the instruction text says 'TWENTY' and there
is not enough space for 'TWENTY-FIVE' even with formatting text.

-  The boss seemed to be trying to fire all the time and the fire sound effect
was  constantly  going  off.  Only  trigger sound effect if boss's weapon fire
doesn't  collide  first  frame.  In addition limit boss to firing when you are
close.

-  Player  to map collision was not exact. This meant it was a little bit more
awkward moving around. Fixed in CPC version.

-  Congratulations screen: Adjustment compared to Spectrum version: Adjusted y
position  of  congratulations text to make it more consistent with 'GAME OVER'
text. No change to memory usage.

-  Bomb  defuse screen: Adjustment compared to Spectrum version: Added message
'ENTER  CODE  TO DEFUSE BOMB' to make it clearer what should be done. Extra 36
bytes used for message and code.

-  Score: On the Spectrum version the score is 5 digits and stored in decimal.
I chose to represent the score as BCD, and therefore it was easier to make the
score  an  even  number  of digits, and 6 was used. Plus with 6 digits it fits
within the HUD better.

-  Score:  On the Spectrum the score digits rolled like a tape player counter.
I removed this on CPC. It was easier for me to update with double buffer.

-  I  adjusted  the  'Aerobomb'  timer  so  it took a lot longer to appear. It
seemed  it would appear more quickly compared to Spectrum making the game more
difficult.

-  I  adjusted  the  overall time from 20 mins to 30 mins. I felt with the CPC
and PCW version running slower in places more time was needed.

-  On  the  Spectrum, when you enter the bomb room the bombs visually flash to
bring  attention  to  their  location  on the screen. This is done by changing
attributes. Nothing is done on CPC. The bombs do not flash.

-  Scrolling  messages  were  removed.  I had trouble with them flickering and
double buffering and didn't have the motivation to fix it fully.

Loading screen
==============

The original had a simplistic loading screen that the publisher put on it.

Map/tile Collision Memory
=========================

The  game  used the Spectrum's screen attributes to define map collision, this
defined  if  a tile could be walked over or not. Therefore it's tile collision
read direct from the attribute RAM.

CPC  doesn't  have  screen  attributes  so  I  had  to  use  an  extra buffer.
Thankfully  because  the  play area is smaller than the screen this buffer was
the size of the play area and not the size of the entire ZX Spectrum attribute
RAM.

The  'attribute'  data  was  converted  to  '00'  can walk and 'FF' can't walk
rather  than the attribute bytes themselves. There is a potential that I could
have  reduced  this  to  a  byte per tile as this is defined for each 8x8 in a
tile. I didn't need to do this in the end.

HUD height in attributes = 8
Screen height in attributes excluding hud = 24-8 = 16
Screen width in attributes = 32

Collision buffer: 16x32 = 512 bytes

Font:
====

Spectrum:

* 1bpp
* 8x8
* Attributes defined with text that the font is displayed with
* Each char takes 8 bytes.
* 96 chars. (32-127)

Takes 768 bytes.

CPC:

* 2bpp
* 8x8
* No transparent pen.
* Each char takes 16 bytes.

Font size 1536 bytes. 768 bytes more than Spectrum.

Optimisation:
-  The font had definitions for all ascii characters from 0-7f including lower
case.  Upper  case  was  only used. Now 59 chars rather than 96 chars. Now 944
bytes.  Saving  592  bytes.  With  this  reduction  still  176 bytes more than
Spectrum version.

Keyboard
========

On  the Spectrum the following is the minimum required to read a keyboard line
(8 keys at once):

ld      a,0bfh                  ; Select keyboard line
in      a,(0feh)    ; read keyboard line

On  the  CPC the keyboard is connected to AY I/O port A and the AY is accessed
via  port A and port C of the 8255. Therefore to read the keyboard you need to
access the AY via the 8255 and this requires multiple steps.

;; It  is assumed that PPI port A is set to output at this point. We use  that
;; as the default.

;; send register number 14 (AY port A) to PPI port A. AY will not use this yet.
ld      bc,&f40e
out     (c),c
;;  set PPI port C bits to indicate to AY it should read the data from the PPI
port A and use that to select a register for reading/writing.
ld              bc,&f6c0
out     (c),c
;; set PPI port C bits to indicate to AY it should go back to 'inactive'.
ld              bc,&f600
out     (c),c

;; set PPI port A to input so we can read the data from the AY
ld      bc,&f792
out     (c),c

;;  with  AY register 14 selected and PPI port A set to input, we can now read
the selected AY register via PPI port A

;;  set  PPI port C bits to indicate to AY it should put the register contents
;;  to PPI port A so we can read them
;;  AND  to  choose  which keyboard line to read. A keyboard line represents 8
;;  keys at a time.
ld      bc,&f640
out     (c),c

;; read PPI port A (this reads
ld              b,&f4
in              a,(c)

;; set PPI port C bits to indicate to AY it should go back to 'inactive'
ld              bc,&f600
out     (c),c

;; restore PPI port A back to output so we can write to AY to make sound.
ld      bc,&f782
out     (c),c

Scanning  the  keyboard  on  the CPC is therefore much much slower than on the
Spectrum.

Frame rate
==========

I  don't  know the frame rate on the Spectrum version. I didn't measure it. On
the  CPC  it's  locked  to  25fps. I found if the frame rate was not locked it
would  vary  from fast if there are few enemies on screen to slow. Therefore I
chose to lock it to make it consistent.

Joystick
========

On  the CPC the joystick is scanned just the same as the keyboard but you only
need to read keyboard line 9 to get all directions and fire buttons.

On the Spectrum the choices are:
- Kempston
- Sinclair
- Cursor

For  all  on  Spectrum  it is like this with a different port depending on the
joystick interface:

in a,(&af)

Scanning the joystick is therefore slower than on the Spectrum.

Score font:
===========

Spectrum:

* 1bpp
* 8x8
* digits 0-9
* Each char takes 8 bytes

Takes 80 bytes.

CPC

* 2bpp
* 8x8
* digits 0-9
* Each char takes 16 bytes

Takes 160 bytes.

Text encoding
=============

Text is encoded as ASCII with control codes to set paper, ink, flashing and bright.
The following each had their own control code and code handler:

- (&0d) new line
- (&13) set bright on/off <byte>
- (&12) set flash on/off <byte>
- (&10) set ink <byte>
- (&11) set paper <byte>
- (&16) set X,Y character coordinates <byte>,<byte>
- (&17) Set X character coordinate <byte>
- (&0b) end of text

Optimisations:

On the CPC these were kept:

- (&0d) new line
- (&16) set X,Y character coordinates <byte>, <byte>
- (&0b) end of text

flashing was removed.

A new control code was added. I call it:
- (&10) set pen and ink <byte>

This replaced set bright on/off, set flash on/off, set ink and set paper.

In addition one code was not used on Spectrum:

&17 was removed.

This saved:

129 bytes - which includes changes to the text to remove the control codes.

Screen addressess
=================

We  store a list of screen addresses for the start of each scanline. This aids
conversion from game coordinates to screen.
This table takes 256x2, 512 bytes.

On  a normal sized CPC screen to go to the next screen address to the right we
would need to use:

inc hl

With a reduced screen set to the size of the Spectrum's we can use:

inc l

The  calculations  to move to next scanline below are similar on both Spectrum
and Amstrad so neither is much faster.

This makes movement around the screen memory similar to the Spectrum.

Screen size
===========

I kept the screen the same size as the Spectrum for two reasons:
1.  The  same  map  can  be used, making the screen wider and showing more map
would  adjust  the  gameplay  and  more code would need to be adjusted to show
this,  collide  with  this, times would need to be adjusted to ensure the game
could be completed.
2.  I  could  use  the  unused parts of the screen to store graphics so that I
didn't need to cut it back to make it fit.

Text drawing
============

The spectrum version draws text and then colours it using attributes.

I  also  wanted  coloured  text  because  it's  more interesting. I could have
changed  the  colour  of  some text using palette changing but this would mean
burning cycles to get to this point.

Therefore  with  mayhem  on  CPC  I  am  limiting  text to a single colour but
allowing me to set the background and foreground colour.
The drawing of the text is slower than on the Spectrum.

To make some screens easier to read I adjusted the layout of the text.

Random numbers
==============

The  game  generated  random  numbers  by  reading  from  the first 8KB of the
Spectrum  ROM.  This could not be used on the CPC and the generated randomness
will  be  different  when  compared  to  the  Spectrum version making the game
slightly different.

In  the  Spectrum  version  every place the random number was fetched used the
same code:

Spectrum version:

        ld      hl,(RandomROMPtr)
        ld      e,(hl)
        inc     hl
        ld      a,h
        and     1fh
        ld      h,a
        ld      (RandomROMPtr),hl
        ld      a,e


Initial copyright page, Instruction question page
=================================================

The instructions and initial copyright pages are only shown once.

In  the Spectrum version these are drawn direct to the screen without the back
buffer.

Therefore  since  this is shown once the CPC code and data for these was moved
into the area used by the second screen before it is used.

These are displayed directly to the first screen without page flipping.

The  page  flipping begins and the second screen is used when the main menu is
shown.

Memory optimisation: ~1kb saved in game.

Instructions
============

In  the  Spectrum version of Mayhem the instructions were presented as a large
scrolling message (made by scrolling attribute data) which is shown just once.

Scrolling  text  of  this  size using software is slow on the CPC and the best
method on cpc is to use hardware scrolling.

Hardware scrolling was not chosen because:
1.  Hardware  scrolling a message is quite fast and I felt a scrolling message
was too hard to read.
2.  Using  hardware  scrolling  an  entire  16KB page is needed and I am using
unused areas of screen to store data.
3.  From  reviews  I've  read of Mayhem the criticism was that the message was
hard to read.
4.  In  keeping  with  games  of  the  day which rarely had hardware scrolling
messages I chose not to use it.

Therefore  on  the  CPC  this  has been changed to display as 4 static screens
using space to proceed to next screen.

The  instructions  and  their  code  was  moved to the area used by the second
screen before it is used and is drawn without double buffer.

Memory optimisations: ~0.5kb saved.

HUD - Memory usage
===

The  Spectrum  used  a  256x64  1-bit image and 256 bytes for attributes which
took  2048+256  bytes.  The  HUD  was setup in it's initial state with initial
score,  lives,  level,  bomb  state  etc. If i had done the same on the CPC it
would have taken 4KB for the image (no attributes).

Optimisations:
-  Identified unique chars used by the hud after removing any dynamic graphics
(score,  level,  energy,  bomb).  Stored  unique  tiles  and  an  array of ids
describing  which  tiles  to draw. 416 bytes for tile graphics + 256 bytes for
ids.  Total 672 bytes. Saving 3424 bytes compared to using a 4KB image on CPC.
In addition it is now less than Spectrum's bitmap version.

On CPC the HUD is drawn to both screens to avoid flicker.

HUD - bomb
===

The  spectrum  had  a  static bomb image, and the colour of the bomb indicated
how  close  the  bomb was to exploding. The colour was changed when each stage
was reached which happens every 2 minutes 30 seconds.

In  the  Spectrum  version  it  was  not  clear how close you were to the bomb
exploding  and  on  the  CPC version to recolour the bomb would require either
changing  a  palette  colour OR drawing the bomb in it's new state. If drawing
the  bomb  then  we  need to potentially store additional graphics to show the
state.

To  work  around this I draw the time remaining for the bomb and the same part
of  the HUD also shows the bomb code digits collected and it is presented like
a warning and like an old style bomb from a film.


HUD - Update
===

With  double  buffer  being  used  when the HUD is updated we need to draw the
updated  parts  of  the  HUD  twice.  Once  for each screen. Therefore for all
elements  I have a counter set to 2 and this causes the HUD to be updated. The
Spectrum  didn't need to do this and therefore the CPC version takes more time
updating the HUD.


Joysticks
=========

The CPC has a single joystick standard.

Mayhem supported Kempston, Sinclair interface 2 and cursor joystick.

Removing the extra joystick types saved around ~100bytes.

Scrolling messages
==================

On the Spectrum scrolling messages were used for:
- display the controls on the main menu
- display 'oops' if the time runs out
- pause/unpause message

Spectrum:
* The code scrolls 32 characters (width of the screen in characters)
* Each character is a single byte in width (8 pixels per byte)
* Each character is 8 lines tall
*  As  each  character is fetched it's data (8 bytes) is copied to RoomXCursor
onwards therefore re-using data.
*  The  game is paused during this time and to make the scroll smooth the game
waits for vsync.
*  To scroll the screen the pixels are moved pixel by pixel from left to right
using  simple  shifts,  the  carry  register  is  used to hold the next pixel.
Through  repeated  shifts the entire line can be scrolled by one pixel. At the
end  of  the  line  a  single  pixel  is  shifted from the stored character to
complete  the  scroll  for  that  line.  The  stored data for the character is
updated  in  place  and shifted for the next scroll update. After 8 pixels are
shifted  the  next  character  is fetched until all 32 characters are scrolled
onto the screen.

The  scroll code is simple because of the 1-bit pixel bitmap of the Spectrum's
screen display.

With the CPC I did implement a smooth text scrolling in mode 1:
* The code scrolls 32 characters
* Each character is 2 bytes wide.
* Each character is 8 lines tall
*  We  can't  re-use  the same data for temporary storage for a character like
the  Spectrum  version because there is not enough room and we would overwrite
some data, therefore we must use some other spare memory.
*  We  can't scroll the same way using the carry flag to store the next pixel.
The CPC's mode uses 2 bits in mode 1 and 4 bits in mode 0. The pixels are also
interleaved.  Therefore  a  pixel based scroll is more complicated compared to
the Spectrum.
*  If  we  are  to  be  scrolling different coloured text we need to store the
re-coloured character.(see drawing text)

This  extra complexity for the CPC is probably why a lot of games use a faster
scroll  -  byte or char based. It makes the scrolling simpler to code and uses
less memory.

In  the  end  I  found  it  took  too  long  to wait for and I had issues with
preventing flickering when used for pause message so I removed it.

Double buffering
================

Mayhem  on  Spectrum  uses  a  back  buffer. The sprites are drawn to the back
buffer.  This  buffer  is  copied entirely to the displayed screen. Using this
method the sprites do not flicker when moving.

backbuffer method for double buffering
======================================

Potentially you only need to store a back buffer for the actual play area.
Therefore the back buffer can take less space. The back buffer may also be
stored linearly so it's form doesn't need to match the screen.

To erase sprites you only need to store the data for one set of sprites.

Presenting the back buffer involves a copy of the back buffer to the display.
This needs to be done top-down to avoid tearing.

Cons:

-  only  need  to  store  a back buffer for the game area. If the hud is large
enough  then this area is small. Only need one set of behind data for sprites.
drawing to screen needs to be done top-to-bottom but can also tear.
- more data can be stored continuous in memory.
- slow on CPC

Backbuffer with "dirty" regions
===============================

To  speed up screen updates, if the game doesn't scroll then you don't need to
copy  the  entire back buffer to the display. Instead you can mark which areas
have been modified (are "dirty") and copy only these to the screen.

The  back buffer could be split into multiple tiles. If a sprite covers a tile
then  the  tile is marked as dirty. When the back buffer is presented you only
copy the dirty tiles.

With this approach you need memory to remember which tiles are dirty.

It is faster to just update the dirty tiles.

When  a sprite is moving you can either dirty a larger area - large enough for
fastest  movement  OR you need two dirty buffers. When transfering updates you
need  to  transfer  both this frame and the previous frames dirty values. Then
you can clear.

Backbuffer method takes 12288+

flipping screens method for double buffering
============================================

Mayhem  on  CPC  uses  a  non-scrolling  flipping  screen  method  for  double
buffering. I found that using a back buffer was too slow.

-  Both  screens need to have the same layout - restriction comes from how the
CRTC generates screen addresses
-  Both  screens  are  restricted in their location in RAM - restriction comes
from how the CRTC generates screen addresses
-  if  the screen is not hardware scrolled, then we can use the "free" areas -
the  areas  not  displayed  to  hold  code/data. With flipping screens, if the
code/data  is  large  then  more  of  this needs to sread across RAM using the
"free" areas of screen memory which are not displayed.
-  If  storing  the  background  behind sprites to erse them, then you need to
store  data for both screens doubling the amount of space required compared to
using a back buffer.
-  Anything  which involves a one time update to the screen (e.g. collecting a
pickup,  updating  the  hud),  needs  to  be duplicated to the current visible
screen to avoid flicker. (flicker happens when one screen has different visual
contents to the other and the difference shows as flickering).

Updating a flipping screen (e.g. updating HUD):
-  either  write  to both screens at the same time (which can require an extra
function, one for normal screen setup and one for this update)
-  OR  write  to  one,  then  when  the screen is flipped, update the screen a
second time using the same function. Then you don't need to update at the next
flip.


If  the  map  is  split  into  static  screens,  like  Mayhem,  then  when you
transition to a new part of the map you do not need to (because these apply to
the previous part of the map):
- erase the sprites from the previous displayed part of the map
- update any graphics within the screen area

You will need to continue to update the HUD.

Double buffering using page flipping of two Spectrum sized screens takes:
-  for  the screens: 64*24*8*2 = 24576 non contiguous bytes or 37% of the 64KB
RAM.
- for the data behind the sprites:

NOTES:
-  When  anything  is  drawn  to one screen you need to mirror it in the other
screen to avoid flicker.
-  If  you  are  drawing a sprite and want to erase it next time the screen is
drawn  to  you  either  need  to  record the tiles it covers, or as in the CPC
version  store a copy of the pixels behind the sprite. This does mean that you
need enough space to store 2 lots of 'behind-sprites' data.

Sprites - drawing
=======

The  screen  doesn't  scroll  therefore  the  choice  was  made  to  store the
background before the sprite is drawn so this can be restored when erasing the
sprite.

If  the  screen  was  software  scrolled  we could choose to redraw the entire
screen and we would not need to do this.

Sprites  are  erased in reverse order than the order when they are drawn. This
ensures the background is correctly restored.

Sprites are erased before being drawn in new position.

Sprites  can  be  at  any  pixel  position,  the sprite data is shifted to the
correct position as it's drawn.

Twice  the  memory  is  needed  to store the background behind sprites because
there needs to be data per screen.

Process:

Screen A is being displayed.
Screen B is being drawn to.

Repeat:

Erase  sprites  for  Screen  B  using  stored  background  data  (Order sprite
4,3,2,1)

Store  the  background behind sprite 1 from screen B to stored background data
for screen B,
Draw sprite 1 to screen B,
Store  the  background behind sprite 2 from screen B to stored background data
for screen B,
Draw sprite 2 to screen B,
Store  the  background behind sprite 3 from screen B to stored background data
for screen B,
Draw sprite 3 to screen B,
Store  the  background behind sprite 4 from screen B to stored background data
for screen B,
Draw sprite 4 to screen B,

Make screen B visible, Screen A is now being drawn to.

Erase  sprites  for  Screen  A using stored background data for screen A(Order
sprite 4,3,2,1)

Store  the  background behind sprite 1 from screen A to stored background data
for screen A,
Draw sprite 1 to screen A,
Store  the  background behind sprite 2 from screen A to stored background data
for screen A,
Draw sprite 2 to screen A,
Store  the  background behind sprite 3 from screen A to stored background data
for screen A,
Draw sprite 3 to screen A,
Store  the  background behind sprite 4 from screen A to stored background data
for screen A,
Draw sprite 4 to screen A,

Make screen A visible, Screen B is now being drawn to.

And repeat the above.

On  the  CPC version the number of enemies has been reduced by half from 10 to
5. This doesn't impact the gameplay that much but reduces slowdown.

Score font
==========

Score  uses  it's  own  font. The numbers could be used from the main font and
would save 160 bytes. 80 bytes less than Spectrum version. I didn't need to do
this.

Sound:
======

The  Spectrum  game  has  simple sound effects. Each sfx was generated by it's
own  bit  of code and was made by writing to the 1-bit speaker. When the sound
is  played the game (but not the bomb countdown) is effectively paused for the
duration of the sound. The noise sound was done by reading the Spectrum's ROM.

With  the CPC version I chose to use the AY-3-8912 sound chip and the sound is
played without pausing the game.

Each  time  the  character  moved a step sound was made. I removed this on CPC
because it became annoying.

For  each sound effect I used Amstrad's SOUND and ENV/ENT commands to create a
sound  effect.  I  then put these numbers into my own sound effect playback. I
used  hardware  envelopes  a lot. I also didn't spend much time doing this and
it's easy to hear.

Memory access
=============

Where  the graphics data on CPC is larger than on Spectrum we need to consider
that  some  operations  that  would  fit  into 8-bit values may require 16-bit
values.

This means:
- any code that performs calculations will need to be updated.
- the new code may take more cycles compared to equivalent on Spectrum.
-  some  additional  code  may need to be added to take the 16-bit values into
account.
-  Where  8-bit  values  have been used the code may assume some registers are
set to 0 (e.g. D register is 0 and E is used for 8-bit value).
This  may  no longer be true with larger data on CPC and the code will need to
be adjusted.

In  addition  with  the  Spectrum  version some data may have been set on page
boundaries  and  with  CPC  are re-arranging the data and with a difference in
size this may no longer be possible.

Hidden Text
========

The  spectrum version has text hidden throughout memory - memory which is then
reused.
This is not included in the CPC version.

5b00-5c00:
FIVE THINGS YOU
NEVER KNEW ABOUT
 SAMANTHA FOX: *
1* She is highly
 intelligent*2*
Her ambition is
to be a nun. *3*
 Her father is n
ot interested in
 money *4* She i
s 5'11" tall *5*
 To make her bre
asts,Madame Tuss
auds had to melt
 down Laurel AND
 Hardy    (ooer)

In loader:

5df8-5eb4: The Young
Lady from Bude.T
here was a young
 lady from Bude,
Who lived in a t
own called Bude,
She walked aroun
d Bude,And had a
 house in Bude,T
hat silly young
lady from Bude.W
here is Bude any
way ?

9e68-9f26: FED UP WIT
H DOGGY DOINGS ?
  YOU NEED THE "
SCORCH-A-POOCH L
AMP POST ELECTRI
FIER".DIRTYDOG D
IES INSTANTLY AS
 HE LIFTS HIS LE
G TO URINATE ON
YOUR HIDDEN BOOB
Y TRAP.(C) 1987
MARK INCLEY.THAN
KS,JAS

a2d8-a3d2:
JOHNNY
MARR ON SEX:"NON
E OF US ARE ACTU
ALLY GAY-MORRISS
EY DOESN'T PARTI
CIPATE IN SEX AT
 THE MOMENT AND
HASN'T DONE DO F
OR A WHILE,HE'S
HAD A LOT OF GIR
LFRIENDS IN THE
PAST AND QUITE A
 FEW MEN FRIENDS
.THE REST OF THE
 BAND,HOWEVER,AR
E ALL SEX MANIAC
S.

Part of data used by stack:

a901-a980:
:************AND
Y ROURKE ON THE
SMITHS:"WE ARE T
HE BEST BAND IN
THE WORLD,THERE'
S NOBODY BETTER.
"************