18884
JEU -> Labyrinthe
© _Public_Domain_ (2023)
 
 
 
Mayhem
cpc
 
 

NOTICE / MANUAL

TXT (1)

NOTICE TEXTE n° 1 (38.9 Ko)

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. Title screen in the disc version made by Kukulcan. 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. "************
 



Goto Top
CPC-POWER/CPCSOFTS, programmation par Kukulcan © 2007-2024 tous droits réservés.
Reproduction sans autorisation interdite. Tous les titres utilisés appartiennent à leurs propriétaires respectifs.
Hébergement Web, Mail et serveurs de jeux haute performance