From 87cea2792c0ce7835e8896f59710e9db90141b60 Mon Sep 17 00:00:00 2001 From: Arnaud <arnaud_bouche@hotmail.com> Date: Fri, 19 Jan 2018 21:03:36 +0100 Subject: [PATCH 01/31] Add files via upload Add sprite color replace functions --- .../M0/cpct_drawSpriteColorizeM0.asm | 203 +++++++++++++++ .../cpct_drawSpriteColorizeM0_asmbindings.s | 36 +++ .../M0/cpct_drawSpriteColorizeM0_cbindings.s | 48 ++++ ...cpct_drawSpriteMaskedAlignedColorizeM0.asm | 215 +++++++++++++++ ...priteMaskedAlignedColorizeM0_asmbindings.s | 36 +++ ...wSpriteMaskedAlignedColorizeM0_cbindings.s | 52 ++++ .../M0/cpct_drawSpriteMaskedColorizeM0.asm | 216 +++++++++++++++ ...t_drawSpriteMaskedColorizeM0_asmbindings.s | 36 +++ ...pct_drawSpriteMaskedColorizeM0_cbindings.s | 48 ++++ .../colorReplace/M0/cpct_spriteColorizeM0.asm | 166 ++++++++++++ .../M0/cpct_spriteColorizeM0_asmbindings.s | 36 +++ .../M0/cpct_spriteColorizeM0_cbindings.s | 48 ++++ .../M0/cpct_spriteMaskedColorizeM0.asm | 175 +++++++++++++ .../cpct_spriteMaskedColorizeM0_asmbindings.s | 36 +++ .../cpct_spriteMaskedColorizeM0_cbindings.s | 48 ++++ .../M1/cpct_drawSpriteColorizeM1.asm | 228 ++++++++++++++++ .../cpct_drawSpriteColorizeM1_asmbindings.s | 35 +++ .../M1/cpct_drawSpriteColorizeM1_cbindings.s | 48 ++++ ...cpct_drawSpriteMaskedAlignedColorizeM1.asm | 239 +++++++++++++++++ ...priteMaskedAlignedColorizeM1_asmbindings.s | 36 +++ ...wSpriteMaskedAlignedColorizeM1_cbindings.s | 53 ++++ .../M1/cpct_drawSpriteMaskedColorizeM1.asm | 246 ++++++++++++++++++ ...t_drawSpriteMaskedColorizeM1_asmbindings.s | 36 +++ ...pct_drawSpriteMaskedColorizeM1_cbindings.s | 48 ++++ .../colorReplace/M1/cpct_spriteColorizeM1.asm | 194 ++++++++++++++ .../M1/cpct_spriteColorizeM1_asmbindings.s | 35 +++ .../M1/cpct_spriteColorizeM1_cbindings.s | 48 ++++ .../M1/cpct_spriteMaskedColorizeM1.asm | 205 +++++++++++++++ .../cpct_spriteMaskedColorizeM1_asmbindings.s | 36 +++ .../cpct_spriteMaskedColorizeM1_cbindings.s | 48 ++++ 30 files changed, 2934 insertions(+) create mode 100644 cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteColorizeM0.asm create mode 100644 cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteColorizeM0_asmbindings.s create mode 100644 cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteColorizeM0_cbindings.s create mode 100644 cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteMaskedAlignedColorizeM0.asm create mode 100644 cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteMaskedAlignedColorizeM0_asmbindings.s create mode 100644 cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteMaskedAlignedColorizeM0_cbindings.s create mode 100644 cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteMaskedColorizeM0.asm create mode 100644 cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteMaskedColorizeM0_asmbindings.s create mode 100644 cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteMaskedColorizeM0_cbindings.s create mode 100644 cpctelera/src/sprites/colorReplace/M0/cpct_spriteColorizeM0.asm create mode 100644 cpctelera/src/sprites/colorReplace/M0/cpct_spriteColorizeM0_asmbindings.s create mode 100644 cpctelera/src/sprites/colorReplace/M0/cpct_spriteColorizeM0_cbindings.s create mode 100644 cpctelera/src/sprites/colorReplace/M0/cpct_spriteMaskedColorizeM0.asm create mode 100644 cpctelera/src/sprites/colorReplace/M0/cpct_spriteMaskedColorizeM0_asmbindings.s create mode 100644 cpctelera/src/sprites/colorReplace/M0/cpct_spriteMaskedColorizeM0_cbindings.s create mode 100644 cpctelera/src/sprites/colorReplace/M1/cpct_drawSpriteColorizeM1.asm create mode 100644 cpctelera/src/sprites/colorReplace/M1/cpct_drawSpriteColorizeM1_asmbindings.s create mode 100644 cpctelera/src/sprites/colorReplace/M1/cpct_drawSpriteColorizeM1_cbindings.s create mode 100644 cpctelera/src/sprites/colorReplace/M1/cpct_drawSpriteMaskedAlignedColorizeM1.asm create mode 100644 cpctelera/src/sprites/colorReplace/M1/cpct_drawSpriteMaskedAlignedColorizeM1_asmbindings.s create mode 100644 cpctelera/src/sprites/colorReplace/M1/cpct_drawSpriteMaskedAlignedColorizeM1_cbindings.s create mode 100644 cpctelera/src/sprites/colorReplace/M1/cpct_drawSpriteMaskedColorizeM1.asm create mode 100644 cpctelera/src/sprites/colorReplace/M1/cpct_drawSpriteMaskedColorizeM1_asmbindings.s create mode 100644 cpctelera/src/sprites/colorReplace/M1/cpct_drawSpriteMaskedColorizeM1_cbindings.s create mode 100644 cpctelera/src/sprites/colorReplace/M1/cpct_spriteColorizeM1.asm create mode 100644 cpctelera/src/sprites/colorReplace/M1/cpct_spriteColorizeM1_asmbindings.s create mode 100644 cpctelera/src/sprites/colorReplace/M1/cpct_spriteColorizeM1_cbindings.s create mode 100644 cpctelera/src/sprites/colorReplace/M1/cpct_spriteMaskedColorizeM1.asm create mode 100644 cpctelera/src/sprites/colorReplace/M1/cpct_spriteMaskedColorizeM1_asmbindings.s create mode 100644 cpctelera/src/sprites/colorReplace/M1/cpct_spriteMaskedColorizeM1_cbindings.s diff --git a/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteColorizeM0.asm b/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteColorizeM0.asm new file mode 100644 index 000000000..13d195147 --- /dev/null +++ b/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteColorizeM0.asm @@ -0,0 +1,203 @@ +;;-----------------------------LICENSE NOTICE------------------------------------ +;; This file is part of CPCtelera: An Amstrad CPC Game Engine +;; Copyright (C) 2017 Arnaud Bouche (Arnaud6128) +;; Copyright (C) 2017 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) +;; +;; This program is free software: you can redistribute it and/or modify +;; it under the terms of the GNU Lesser General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU Lesser General Public License for more details. +;; +;; You should have received a copy of the GNU Lesser General Public License +;; along with this program. If not, see <http://www.gnu.org/licenses/>. +;;------------------------------------------------------------------------------- +.module cpct_sprites + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; +;; Function: cpct_drawSpriteColorizeM0 +;; +;; Directly replace a color and draw a sprite to video memory. +;; +;; C Definition: +;; void <cpct_drawSpriteColorizeM0> (void* *sprite*, void* *memory*, <u8> *width*, <u8> *height*, <u8> *oldColor*, <u8> *newColor*) __z88dk_callee; +;; +;; Input Parameters (8 bytes): +;; (2B HL') sprite - Source Sprite Pointer (array of pixel data) +;; (2B DE') memory - Destination video memory pointer +;; (1B C' ) height - Sprite Height in bytes (>0) +;; (1B B' ) width - Sprite Width in *bytes* (Beware, *not* in pixels!) +;; (1B L ) oldColor - Color to replace +;; (1B H ) newColor - New color +;; +;; Assembly call (Input parameters on registers): +;; > call cpct_drawSpriteColorizeM0_asm +;; +;; Parameter Restrictions: +;; * *sprite* must be an array containing sprite's pixels data in screen pixel format. +;; Sprite must be rectangular and all bytes in the array must be consecutive pixels, +;; starting from top-left corner and going left-to-right, top-to-bottom down to the +;; bottom-right corner. Total amount of bytes in pixel array should be *width* x *height*. +;; * *memory* could be any place in memory, inside or outside current video memory. It +;; will be equally treated as video memory (taking into account CPC's video memory +;; disposition). This lets you copy sprites to software or hardware backbuffers, and +;; not only video memory. +;; * *width* must be the width of the sprite *in bytes*. Always remember that the width must be +;; expressed in bytes and *not* in pixels. +;; The correspondence is mode 0 : 1 byte = 2 pixels +;; * *height* must be the height of the sprite in bytes, and must be greater than 0. +;; There is no practical upper limit to this value. Height of a sprite in +;; bytes and pixels is the same value, as bytes only group consecutive pixels in +;; the horizontal space. +;; * *oldColor* must be the index of color (0 to 15) to replace +;; * *newColor* must be the index of the new color (0 to 15) +;; +;; Known limitations: +;; * This function does not do any kind of boundary check or clipping. If you +;; try to draw sprites on the frontier of your video memory or screen buffer +;; if might potentially overwrite memory locations beyond boundaries. This +;; could cause your program to behave erratically, hang or crash. Always +;; take the necessary steps to guarantee that you are drawing inside screen +;; or buffer boundaries. +;; * As this function receives a byte-pointer to memory, it can only +;; draw byte-sized and byte-aligned sprites. This means that the box cannot +;; start on non-byte aligned pixels (like odd-pixels, for instance) and +;; their sizes must be a multiple of a byte (2 in mode 0, 4 in mode 1 and +;; 8 in mode 2). +;; * This function *will not work from ROM*, as it uses self-modifying code. +;; * This function requires the CPC firmware to be DISABLED. Otherwise, random crashes might happen due to side effects. +;; +;; Destroyed Register values: +;; AF, BC, DE, HL, BC', DE', HL', IX +;; +;; Required memory: +;; C-bindings - 118 bytes +;; ASM-bindings - 108 bytes +;; +;; Time Measures: +;; (start code) +;; Case | microSecs (us) | CPU Cycles +;; ---------------------------------------------------------------- +;; | 29 + (62 + 23W)H | 116 + (248 + 92W)H +;; ---------------------------------------------------------------- +;; W=2,H=16 | 1757 | 7028 +;; W=4,H=32 | 4957 | 19828 +;; ---------------------------------------------------------------- +;; Asm saving | -16 | -64 +;; ---------------------------------------------------------------- +;; (end code) +;; W = *width* in bytes, H = *height* in bytes, HH = [(H-1)/8] +;; +;; Credits: +;; Original routine optimized by @Docent and discussed in CPCWiki : +;; http://www.cpcwiki.eu/forum/programming/cpctelera-colorize-sprite/ +;; +;; Thanks to all of them for their help and support. +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +.globl dc_mode0_ct + +;; Macro to convert Pixel to xAxC xBxD format +.macro convertPixel + ;; From cpct_px2byteM0 + ld bc, #dc_mode0_ct ;; [3] BC points to conversion table (dc_mode0_ct) + + ;; Compute BC += A + add c ;; [1] | C += A + ld c, a ;; [1] | + sub a ;; [1] A = 0 (preserving Carry Flag) + adc b ;; [1] | B += Carry + ld b, a ;; [1] | + + ;; A = *(BC + A) + ld a, (bc) ;; [2] A = Value stored at the table pointed by BC +.endm + + ;; Convert newColor to pixel format (E) + ld a, h ;; [1] A = H new color index + convertPixel ;; [10] | Convert into A + ld e, a ;; [1] | E = A new color : xAxC xBxD + + ;; Convert oldColor to pixel format (D) + ld a, l ;; [1] A = L old color index + convertPixel ;; [10] | Convert into A + ld d, a ;; [1] | D = A old color : xAxC xBxD + + ld c, #0x55 ;; [2] C = Mask to get pixel A : xAxC xBxD + + exx ;; [1] Switch to Alternate registers + + ld__ixl_c ;; [1] IXL = C (Width) + ld c, b ;; [1] C = B (Height) + +convertLoop: + ld (startLine), de ;; [6] Store DE start line (DestMem) + ld__b_ixl ;; [2] B = IXL (Sprite Width) + +lineLoop: + ld a, (hl) ;; [2] A = (HL) current Byte of sprite + exx ;; [1] Switch to Default registers + + ld l, a ;; [1] L = A current Byte of sprite : ABAB ABAB + and c ;; [2] A |= C (C = 0x55) : xBxB xBxB + + cp d ;; [1] Test if pixel (A) is the old colour to be replaced (D) + jr nz, readPixelA ;; [2/3] If not equal go to next pixel + ld a, e ;; [1] else A = new colour to set (E) + +;; Pixel Mode 0 = ABAB ABAB +readPixelA: + ld h, a ;; [1] H = A (current colorized sprite) : xBxB xBxB + ld a, l ;; [1] L = A current Byte of sprite : ABAB ABAB + rrca ;; [1] A (current byte of sprite) >> 1 : ABAB ABAB -> xABA BABA + and c ;; [2] A |= Mask (0x55) : xAxA xAxA + + cp d ;; [1] Test if pixel (A) is the old colour to be replaced (D) + jr nz, readPixelB ;; [2/3] If not equal go to next pixel + ld a, e ;; [1] else A = new colour to set (E) + +readPixelB: + rlca ;; [1] A = xAxA xAxA << 1 : AxAx AxAx + or h ;; [1] A |= H (xBxB xBxB) : ABAB ABAB + + exx ;; [1] Switch to Alternate registers + +drawByte: + ld (de), a ;; [2] Update current sprite byte with pixels + inc hl ;; [2] Next byte sprite source + inc de ;; [2] Next byte sprite colorized + djnz lineLoop ;; [3] Decrement B (Width) if B != 0 goto lineLoop + + dec c ;; [1] Decrement C (Height) + jr z, end ;; [2/3] If C == O goto end + +startLine = .+1 ;; Placeholder for the Start line adress + ld de, #0000 ;; [3] DE = Start Line + + ld a, d ;; [1] Start of next pixel line normally is 0x0800 bytes away. + add #0x08 ;; [2] so we add it to DE (just by adding 0x08 to D) + ld d, a ;; [1] + and #0x38 ;; [2] We check if we have crossed memory boundary (every 8 pixel lines).. + + jr nz, convertLoop ;; [2/3] .. by checking the 4 bits that identify present memory line. + ;; .... If 0, we have crossed boundaries + +dms_sprite_8bit_boundary_crossed: + ld a, e ;; [1] DE = DE + 0xC050h + add #0x50 ;; [2] -- Relocate DE pointer to the start of the next pixel line: + ld e, a ;; [1] -- DE is moved forward 3 memory banks plus 50 bytes (4000h * 3) + ld a, d ;; [1] -- which effectively is the same as moving it 1 bank backwards and then + adc #0xC0 ;; [2] -- 50 bytes forwards (which is what we want to move it to the next pixel line) + ld d, a ;; [1] -- Calculations are made with 8 bit maths as it is faster than other alternatives here + + jr convertLoop ;; [3] Jump to continue with next pixel line + +end: + ;; Return is included in bindings + + diff --git a/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteColorizeM0_asmbindings.s b/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteColorizeM0_asmbindings.s new file mode 100644 index 000000000..d5930a9aa --- /dev/null +++ b/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteColorizeM0_asmbindings.s @@ -0,0 +1,36 @@ +;;-----------------------------LICENSE NOTICE------------------------------------ +;; This file is part of CPCtelera: An Amstrad CPC Game Engine +;; Copyright (C) 2017 Arnaud Bouche (Arnaud6128) +;; Copyright (C) 2017 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) +;; +;; This program is free software: you can redistribute it and/or modify +;; it under the terms of the GNU Lesser General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU Lesser General Public License for more details. +;; +;; You should have received a copy of the GNU Lesser General Public License +;; along with this program. If not, see <http://www.gnu.org/licenses/>. +;;------------------------------------------------------------------------------- +.module cpct_sprites + +.include "../../../macros/cpct_undocumentedOpcodes.s" + +;; +;; ASM bindings for <cpct_drawSpriteColorizeM0> +;; +cpct_drawSpriteColorizeM0_asm:: ;; Assembly entry point + + ;; GET Parameters from the stack + ld (dms_restore_ix + 2), ix ;; [6] Save IX to restore it before returning + pop hl ;; [3] HL = Return Address + +;;.include /cpct_drawSpriteColorizeM0.asm/ + +dms_restore_ix: + ld ix, #0000 ;; [4] Restore IX before returning + ret ;; [3] Return to caller \ No newline at end of file diff --git a/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteColorizeM0_cbindings.s b/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteColorizeM0_cbindings.s new file mode 100644 index 000000000..ac5d57084 --- /dev/null +++ b/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteColorizeM0_cbindings.s @@ -0,0 +1,48 @@ +;;-----------------------------LICENSE NOTICE------------------------------------ +;; This file is part of CPCtelera: An Amstrad CPC Game Engine +;; Copyright (C) 2017 Arnaud Bouche (Arnaud6128) +;; Copyright (C) 2017 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) +;; +;; This program is free software: you can redistribute it and/or modify +;; it under the terms of the GNU Lesser General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU Lesser General Public License for more details. +;; +;; You should have received a copy of the GNU Lesser General Public License +;; along with this program. If not, see <http://www.gnu.org/licenses/>. +;;------------------------------------------------------------------------------- +.module cpct_sprites + +.include "../../../macros/cpct_undocumentedOpcodes.s" + +;; +;; C bindings for <cpct_drawSpriteColorizeM0> +;; +;; 33 us, 10 bytes +;; +_cpct_drawSpriteColorizeM0:: + + ;; GET Parameters from the stack + ld (dms_restore_ix + 2), ix ;; [6] Save IX to restore it before returning + pop hl ;; [3] HL = Return Address + + exx + pop hl ;; [3] HL' = Source address (Sprite) + pop de ;; [3] DE' = Destination Memory + pop bc ;; [5] BC' = (B = Sprite Height, C = Width) + exx + + ex (sp), hl ;; [6] HL = (H = newColor, L = oldColor) + ;; ... and leave Return Address at (SP) as we don't need to restore + ;; ... stack status because callin convention is __z88dk_callee + +.include /cpct_drawSpriteColorizeM0.asm/ + +dms_restore_ix: + ld ix, #0000 ;; [4] Restore IX before returning + ret ;; [3] Return to caller \ No newline at end of file diff --git a/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteMaskedAlignedColorizeM0.asm b/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteMaskedAlignedColorizeM0.asm new file mode 100644 index 000000000..21308854d --- /dev/null +++ b/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteMaskedAlignedColorizeM0.asm @@ -0,0 +1,215 @@ +;;-----------------------------LICENSE NOTICE------------------------------------ +;; This file is part of CPCtelera: An Amstrad CPC Game Engine +;; Copyright (C) 2017 Arnaud Bouche (Arnaud6128) +;; Copyright (C) 2017 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) +;; +;; This program is free software: you can redistribute it and/or modify +;; it under the terms of the GNU Lesser General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU Lesser General Public License for more details. +;; +;; You should have received a copy of the GNU Lesser General Public License +;; along with this program. If not, see <http://www.gnu.org/licenses/>. +;;------------------------------------------------------------------------------- +.module cpct_sprites + +.globl dc_mode0_ct + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; +;; Function: cpct_drawSpriteMaskedAlignedColorizeM0 +;; +;; Directly replace a color and draw a sprite Masked Aligned to video memory. +;; +;; C Definition: +;; void <cpct_drawSpriteMaskedAlignedColorizeM0> (void* *sprite*, void* *memory*, <u8> *width*, <u8> *height*, +;; <u8> *oldColor*, <u8> *newColor*, <u8*> *pmasktable*) __z88dk_callee; +;; +;; Input Parameters (10 bytes): +;; (2B HL') sprite - Source Sprite Pointer (array of pixel data) +;; (2B DE') memory - Destination video memory pointer +;; (1B C' ) height - Sprite Height in bytes (>0) +;; (1B B' ) width - Sprite Width in *bytes* (Beware, *not* in pixels!) +;; (1B E ) oldColor - Color to replace +;; (1B D ) newColor - New color +;; (2B HL) pmasktable - Pointer to the aligned mask table used to create transparency +;; +;; Assembly call (Input parameters on registers): +;; > call cpct_drawSpriteMaskedAlignedColorizeM0_asm +;; +;; Parameter Restrictions: +;; * *sprite* must be an array containing sprite's pixels data in screen pixel format +;; Sprite must be rectangular and all bytes in the array must be consecutive pixels, +;; starting from top-left corner and going left-to-right, top-to-bottom down to the +;; bottom-right corner. Total amount of bytes in pixel array should be *width* x *height*. +;; * *memory* could be any place in memory, inside or outside current video memory. It +;; will be equally treated as video memory (taking into account CPC's video memory +;; disposition). This lets you copy sprites to software or hardware backbuffers, and +;; not only video memory. +;; * *width* must be the width of the sprite *in bytes*. Always remember that the width must be +;; expressed in bytes and *not* in pixels. +;; The correspondence is mode 0 : 1 byte = 2 pixels +;; * *height* must be the height of the sprite in bytes, and must be greater than 0. +;; There is no practical upper limit to this value. Height of a sprite in +;; bytes and pixels is the same value, as bytes only group consecutive pixels in +;; the horizontal space. +;; * *oldColor* must be the index of color (0 to 15) to replace +;; * *newColor* must be the index of the new color (0 to 15) +;; +;; Known limitations: +;; * This function does not do any kind of boundary check or clipping. If you +;; try to draw sprites on the frontier of your video memory or screen buffer +;; if might potentially overwrite memory locations beyond boundaries. This +;; could cause your program to behave erratically, hang or crash. Always +;; take the necessary steps to guarantee that you are drawing inside screen +;; or buffer boundaries. +;; * As this function receives a byte-pointer to memory, it can only +;; draw byte-sized and byte-aligned sprites. This means that the box cannot +;; start on non-byte aligned pixels (like odd-pixels, for instance) and +;; their sizes must be a multiple of a byte (2 in mode 0, 4 in mode 1 and +;; 8 in mode 2). +;; * This function *will not work from ROM*, as it uses self-modifying code. +;; * This function requires the CPC firmware to be DISABLED. Otherwise, random crashes might happen due to side effects. +;; +;; Destroyed Register values: +;; AF, BC, DE, HL, BC', DE', HL', IX +;; +;; Required memory: +;; C-bindings - 112 bytes +;; ASM-bindings - 96 bytes +;; +;; Time Measures: +;; (start code) +;; Case | microSecs (us) | CPU Cycles +;; ---------------------------------------------------------------- +;; | 32 + (58 + 20W)H | 128 + (232 + 80W)H +;; ---------------------------------------------------------------- +;; W=2,H=16 | 1600 | 6400 +;; W=4,H=32 | 4448 | 17792 +;; ---------------------------------------------------------------- +;; Asm saving | -16 | -64 +;; ---------------------------------------------------------------- +;; (end code) +;; W = *width* in bytes, H = *height* in bytes, HH = [(H-1)/8] +;; +;; Credits: +;; Original routine optimized by @Docent and discussed in CPCWiki : +;; http://www.cpcwiki.eu/forum/programming/cpctelera-colorize-sprite/ +;; +;; Thanks to all of them for their help and support. +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;; Macro to convert Pixel to xAxC xBxD format +.macro convertPixel + ;; From cpct_px2byteM0 + ld bc, #dc_mode0_ct ;; [3] BC points to conversion table (dc_mode0_ct) + + ;; Compute BC += A + add c ;; [1] | C += A + ld c, a ;; [1] | + sub a ;; [1] A = 0 (preserving Carry Flag) + adc b ;; [1] | B += Carry + ld b, a ;; [1] | + + ;; A = *(BC + A) + ld a, (bc) ;; [2] A = Value stored at the table pointed by BC +.endm + + ;; Convert newColor to pixel format (E) + ld a, h ;; [1] A = H new color index + convertPixel ;; [10] | Convert into A + ld e, a ;; [1] | E = A new color : xAxC xBxD + + ;; Convert oldColor to pixel format (D) + ld a, l ;; [1] A = L old color index + convertPixel ;; [10] | Convert into A + ld b, d + ld d, a ;; [1] | D = A old color : xAxC xBxD + + ld c, #0x55 ;; [2] C = Mask to get pixel A : xAxC xBxD + exx ;; [1] Switch to Alternate registers + + ld__ixl_c ;; [1] IXL = C (Width) + ld c, b ;; [1] C = B (Height) + +convertLoop: + push de ;; [4] Store DE start line (DestMem) + ld__b_ixl ;; [2] B = IXL (Sprite Width) + +lineLoop: + ld a, (hl) ;; [2] A = (HL) current Byte of sprite + exx ;; [1] Switch to Default registers + + ld l, a ;; [1] L = A current Byte of sprite : ABAB ABAB + and c ;; [2] A |= C (C = 0x55) : xBxB xBxB + + cp d ;; [1] Test if pixel (A) is the old colour to be replaced (D) + jr nz, readPixelA ;; [2/3] If not equal go to next pixel + ld a, e ;; [1] else A = new colour to set (E) + +;; Pixel Mode 0 = ABAB ABAB +readPixelA: + ld h, a ;; [1] H = A (current colorized sprite) : xBxB xBxB + ld a, l ;; [1] L = A current Byte of sprite : ABAB ABAB + rrca ;; [1] A (current byte of sprite) >> 1 : ABAB ABAB -> xABA BABA + and c ;; [2] A |= Mask (0x55) : xAxA xAxA + + cp d ;; [1] Test if pixel (A) is the old colour to be replaced (D) + jr nz, readPixelB ;; [2/3] If not equal go to next pixel + ld a, e ;; [1] else A = new colour to set (E) + +readPixelB: + rlca ;; [1] A = xAxA xAxA << 1 : AxAx AxAx + or h ;; [1] A |= H (xBxB xBxB) : ABAB ABAB + +drawByte: + ld h, b ;; [1] H = B (Masked table adress High Byte) + ld l, a ;; [1] Access mask table element (table must be 256-byte aligned) + exx ;; [1] Switch to Alternate registers + + ld a, (de) ;; [2] Get the value of the byte of the screen where we are going to draw + exx ;; [1] Switch to Default registers + + and (hl) ;; [2] Erase background part that is to be overwritten (Mask step 1) + or l ;; [1] Add up background and sprite information in one byte (Mask step 2) + exx ;; [1] Switch to Alternate registers + + ld (de), a ;; [2] Save modified background + sprite data information into memory + + inc hl ;; [2] Next byte sprite source + inc de ;; [2] Next byte sprite colorized + djnz lineLoop ;; [3] Decrement B (Width) if B != 0 goto lineLoop + + dec c ;; [1] Decrement C (Height) + jr z, end ;; [2/3] If C == O goto end + + pop de ;; [3] Restore DE start line (DestMem) + + ld a, d ;; [1] Start of next pixel line normally is 0x0800 bytes away. + add #0x08 ;; [2] so we add it to DE (just by adding 0x08 to D) + ld d, a ;; [1] + and #0x38 ;; [2] We check if we have crossed memory boundary (every 8 pixel lines).. + + jr nz, convertLoop ;; [2/3] .. by checking the 4 bits that identify present memory line. + ;; .... If 0, we have crossed boundaries + +dms_sprite_8bit_boundary_crossed: + ld a, e ;; [1] DE = DE + 0xC050h + add #0x50 ;; [2] -- Relocate DE pointer to the start of the next pixel line: + ld e, a ;; [1] -- DE is moved forward 3 memory banks plus 50 bytes (4000h * 3) + ld a, d ;; [1] -- which effectively is the same as moving it 1 bank backwards and then + adc #0xC0 ;; [2] -- 50 bytes forwards (which is what we want to move it to the next pixel line) + ld d, a ;; [1] -- Calculations are made with 8 bit maths as it is faster than other alternatives here + + jr convertLoop ;; [3] Jump to continue with next pixel line + +end: + pop de ;; [3] Empty stack by getting last element (DestMem) + ;; Return is included in bindings + + diff --git a/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteMaskedAlignedColorizeM0_asmbindings.s b/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteMaskedAlignedColorizeM0_asmbindings.s new file mode 100644 index 000000000..7828b8736 --- /dev/null +++ b/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteMaskedAlignedColorizeM0_asmbindings.s @@ -0,0 +1,36 @@ +;;-----------------------------LICENSE NOTICE------------------------------------ +;; This file is part of CPCtelera: An Amstrad CPC Game Engine +;; Copyright (C) 2017 Arnaud Bouche (Arnaud6128) +;; Copyright (C) 2017 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) +;; +;; This program is free software: you can redistribute it and/or modify +;; it under the terms of the GNU Lesser General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU Lesser General Public License for more details. +;; +;; You should have received a copy of the GNU Lesser General Public License +;; along with this program. If not, see <http://www.gnu.org/licenses/>. +;;------------------------------------------------------------------------------- +.module cpct_sprites + +.include "../../../macros/cpct_undocumentedOpcodes.s" + +;; +;; ASM bindings for <cpct_drawSpriteMaskedAlignedColorizeM0> +;; +cpct_drawSpriteMaskedAlignedColorizeM0_asm:: ;; Assembly entry point + + ;; GET Parameters from the stack + ld (dms_restore_ix + 2), ix ;; [6] Save IX to restore it before returning + pop hl ;; [3] HL = Return Address + +.include /cpct_drawSpriteMaskedAlignedColorizeM0.asm/ + +dms_restore_ix: + ld ix, #0000 ;; [4] Restore IX before returning + ret ;; [3] Return to caller \ No newline at end of file diff --git a/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteMaskedAlignedColorizeM0_cbindings.s b/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteMaskedAlignedColorizeM0_cbindings.s new file mode 100644 index 000000000..001ae99c3 --- /dev/null +++ b/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteMaskedAlignedColorizeM0_cbindings.s @@ -0,0 +1,52 @@ +;;-----------------------------LICENSE NOTICE------------------------------------ +;; This file is part of CPCtelera: An Amstrad CPC Game Engine +;; Copyright (C) 2017 Arnaud Bouche (Arnaud6128) +;; Copyright (C) 2017 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) +;; +;; This program is free software: you can redistribute it and/or modify +;; it under the terms of the GNU Lesser General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU Lesser General Public License for more details. +;; +;; You should have received a copy of the GNU Lesser General Public License +;; along with this program. If not, see <http://www.gnu.org/licenses/>. +;;------------------------------------------------------------------------------- +.module cpct_sprites + +.include "../../../macros/cpct_undocumentedOpcodes.s" + +;; +;; C bindings for <cpct_drawSpriteMaskedAlignedColorizeM0> +;; +;; 39 us, 16 bytes +;; +_cpct_drawSpriteMaskedAlignedColorizeM0:: + + ;; GET Parameters from the stack + ld (dms_restore_ix + 2), ix ;; [6] Save IX to restore it before returning + pop hl ;; [3] HL = Return Address + + exx ;; [1] Switch to Alternate registers + pop hl ;; [3] HL' = Source address (Sprite) + pop de ;; [3] DE' = Destination Memory + pop bc ;; [5] BC' = (B = Sprite Height, C = Width) + + exx ;; [1] Switch to Default registers + pop de ;; [3] DE = (D = newColor, E = oldColor) + + ex (sp), hl ;; [6] HL = Table Mask address + ;; ... and leave Return Address at (SP) as we don't need to restore + ;; ... stack status because callin convention is __z88dk_callee + + ex de, hl ;; [1] HL <-> DE + +.include /cpct_drawSpriteMaskedAlignedColorizeM0.asm/ + +dms_restore_ix: + ld ix, #0000 ;; [4] Restore IX before returning + ret ;; [3] Return to caller \ No newline at end of file diff --git a/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteMaskedColorizeM0.asm b/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteMaskedColorizeM0.asm new file mode 100644 index 000000000..eb9fd04e4 --- /dev/null +++ b/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteMaskedColorizeM0.asm @@ -0,0 +1,216 @@ +;;-----------------------------LICENSE NOTICE------------------------------------ +;; This file is part of CPCtelera: An Amstrad CPC Game Engine +;; Copyright (C) 2017 Arnaud Bouche +;; Copyright (C) 2017 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) +;; +;; This program is free software: you can redistribute it and/or modify +;; it under the terms of the GNU Lesser General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU Lesser General Public License for more details. +;; +;; You should have received a copy of the GNU Lesser General Public License +;; along with this program. If not, see <http://www.gnu.org/licenses/>. +;;------------------------------------------------------------------------------- +.module cpct_sprites + +.globl dc_mode0_ct + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; +;; Function: cpct_drawSpriteMaskedColorizeM0 +;; +;; Directly replace a color and draw a sprite Masked to video memory. +;; +;; C Definition: +;; void <cpct_drawSpriteMaskedColorizeM0> (void* *sprite*, void* *memory*, <u8> *width*, <u8> *height*, <u8> *oldColor*, <u8> *newColor*) __z88dk_callee; +;; +;; Input Parameters (8 bytes): +;; (2B HL') sprite - Source Sprite Pointer (array of pixel data) +;; (2B DE') memory - Destination video memory pointer +;; (1B C' ) height - Sprite Height in bytes (>0) +;; (1B B' ) width - Sprite Width in *bytes* (Beware, *not* in pixels!) +;; (1B L ) oldColor - Color to replace +;; (1B H ) newColor - New color +;; +;; Assembly call (Input parameters on registers): +;; > call cpct_drawSpriteMaskedColorizeM0_asm +;; +;; Parameter Restrictions: +;; * *sprite* must be an array containing sprite's pixels data in screen pixel format +;; along with mask data. Each mask byte will contain enabled bits as those that should +;; be picked from the background (transparent) and disabled bits for those that will +;; be printed from sprite colour data. Each mask data byte must precede its associated +;; colour data byte. +;; Sprite must be rectangular and all bytes in the array must be consecutive pixels, +;; starting from top-left corner and going left-to-right, top-to-bottom down to the +;; bottom-right corner. Total amount of bytes in pixel array should be +;; 2 x *width* x *height* (mask data doubles array size). +;; * *memory* could be any place in memory, inside or outside current video memory. It +;; will be equally treated as video memory (taking into account CPC's video memory +;; disposition). This lets you copy sprites to software or hardware backbuffers, and +;; not only video memory. +;; * *width* must be the width of the sprite *in bytes*. Always remember that the width must be +;; expressed in bytes and *not* in pixels. +;; The correspondence is mode 0 : 1 byte = 2 pixels +;; * *height* must be the height of the sprite in bytes, and must be greater than 0. +;; There is no practical upper limit to this value. Height of a sprite in +;; bytes and pixels is the same value, as bytes only group consecutive pixels in +;; the horizontal space. +;; * *oldColor* must be the index of color (0 to 15) to replace +;; * *newColor* must be the index of the new color (0 to 15) +;; +;; Known limitations: +;; * This function does not do any kind of boundary check or clipping. If you +;; try to draw sprites on the frontier of your video memory or screen buffer +;; if might potentially overwrite memory locations beyond boundaries. This +;; could cause your program to behave erratically, hang or crash. Always +;; take the necessary steps to guarantee that you are drawing inside screen +;; or buffer boundaries. +;; * As this function receives a byte-pointer to memory, it can only +;; draw byte-sized and byte-aligned sprites. This means that the box cannot +;; start on non-byte aligned pixels (like odd-pixels, for instance) and +;; their sizes must be a multiple of a byte (2 in mode 0, 4 in mode 1 and +;; 8 in mode 2). +;; * This function *will not work from ROM*, as it uses self-modifying code. +;; * This function requires the CPC firmware to be DISABLED. Otherwise, random crashes might happen due to side effects. +;; +;; Destroyed Register values: +;; AF, BC, DE, HL, BC', DE', HL', IX +;; +;; Required memory: +;; C-bindings - 115 bytes +;; ASM-bindings - 102 bytes +;; +;; Time Measures: +;; (start code) +;; Case | microSecs (us) | CPU Cycles +;; ---------------------------------------------------------------- +;; Best | 29 + (50 + 36W)H | 116 + (200 + 144W)H +;; ---------------------------------------------------------------- +;; W=2,H=16 | 1981 | 7924 +;; W=4,H=32 | 6237 | 24948 +;; ---------------------------------------------------------------- +;; Asm saving | -16 | -64 +;; ---------------------------------------------------------------- +;; (end code) +;; W = *width* in bytes, H = *height* in bytes, HH = [(H-1)/8] +;; +;; Credits: +;; Original routine optimized by @Docent and discussed in CPCWiki : +;; http://www.cpcwiki.eu/forum/programming/cpctelera-colorize-sprite/ +;; +;; Thanks to all of them for their help and support. +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;; Macro to convert Pixel to xAxC xBxD format +.macro convertPixel + ;; From cpct_px2byteM0 + ld bc, #dc_mode0_ct ;; [3] BC points to conversion table (dc_mode0_ct) + + ;; Compute BC += A + add c ;; [1] | C += A + ld c, a ;; [1] | + sub a ;; [1] A = 0 (preserving Carry Flag) + adc b ;; [1] | B += Carry + ld b, a ;; [1] | + + ;; A = *(BC + A) + ld a, (bc) ;; [2] A = Value stored at the table pointed by BC +.endm + + ;; Convert newColor to pixel format (E) + ld a, h ;; [1] A = H new color index + convertPixel ;; [10] | Convert into A + ld e, a ;; [1] | E = A new color : xAxC xBxD + + ;; Convert oldColor to pixel format (D) + ld a, l ;; [1] A = L old color index + convertPixel ;; [10] | Convert into A + ld d, a ;; [1] | D = A old color : xAxC xBxD + + ld c, #0x55 ;; [2] C = Mask to get pixel A : xAxC xBxD + + exx ;; [1] Switch to Alternate registers + + ld__ixl_c ;; [1] IXL = C (Width) + ld c, b ;; [1] C = B (Height) + +convertLoop: + ld (startLine), de ;; [6] Store DE start line (DestMem) + ld__b_ixl ;; [2] B = IXL (Sprite Width) + +lineLoop: + inc hl ;; [2] Next byte sprite Color source + ld a, (hl) ;; [2] A = (HL) current Byte of sprite Color + dec hl ;; [2] Previous byte sprite Mask source + + exx ;; [1] Switch to Default registers + + ld l, a ;; [1] L = A current Byte of sprite : ABAB ABAB + and c ;; [2] A |= C (C = 0x55) : xBxB xBxB + + cp d ;; [1] Test if pixel (A) is the old colour to be replaced (D) + jr nz, readPixelA ;; [2/3] If not equal go to next pixel + ld a, e ;; [1] else A = new colour to set (E) + +;; Pixel Mode 0 = ABAB ABAB +readPixelA: + ld h, a ;; [1] H = A (current colorized sprite) : xBxB xBxB + ld a, l ;; [1] L = A current Byte of sprite : ABAB ABAB + rrca ;; [1] A (current byte of sprite) >> 1 : ABAB ABAB -> xABA BABA + and c ;; [2] A |= Mask (0x55) : xAxA xAxA + + cp d ;; [1] Test if pixel (A) is the old colour to be replaced (D) + jr nz, readPixelB ;; [2/3] If not equal go to next pixel + ld a, e ;; [1] else A = new colour to set (E) + +readPixelB: + rlca ;; [1] A = xAxA xAxA << 1 : AxAx AxAx + or h ;; [1] A |= H (xBxB xBxB) : ABAB ABAB + +drawByte: + exx ;; [1] Switch to Alternate registers + ld (sprite_color), a ;; [4] sprite_color = A (Sprite Byte) + + ld a, (de) ;; [2] Get next background byte into A + and (hl) ;; [2] Erase background part that is to be overwritten (Mask step 1) + inc hl ;; [3] HL += 1 => Point HL to Sprite Colour information +sprite_color = .+1 ;; Placeholder for the Sprite Color computed + or #00 ;; [2] Add up background and sprite information in one byte (Mask step 2) + ld (de), a ;; [2] Save modified background + sprite data information into memory + + inc hl ;; [2] Next byte sprite source + inc de ;; [2] Next byte Dest Memory + djnz lineLoop ;; [3] Decrement B (Width) if B != 0 goto lineLoop + + dec c ;; [1] Decrement C (Height) + jr z, end ;; [2/3] If C == O goto end + +startLine = .+1 ;; Placeholder for the Start line adress + ld de, #0000 ;; [3] DE = Start Line + + ld a, d ;; [1] Start of next pixel line normally is 0x0800 bytes away. + add #0x08 ;; [2] so we add it to DE (just by adding 0x08 to D) + ld d, a ;; [1] + and #0x38 ;; [2] We check if we have crossed memory boundary (every 8 pixel lines).. + + jr nz, convertLoop ;; [2/3] .. by checking the 4 bits that identify present memory line. + ;; .... If 0, we have crossed boundaries + +dms_sprite_8bit_boundary_crossed: + ld a, e ;; [1] DE = DE + 0xC050h + add #0x50 ;; [2] -- Relocate DE pointer to the start of the next pixel line: + ld e, a ;; [1] -- DE is moved forward 3 memory banks plus 50 bytes (4000h * 3) + ld a, d ;; [1] -- which effectively is the same as moving it 1 bank backwards and then + adc #0xC0 ;; [2] -- 50 bytes forwards (which is what we want to move it to the next pixel line) + ld d, a ;; [1] -- Calculations are made with 8 bit maths as it is faster than other alternatives here + + jr convertLoop ;; [3] Jump to continue with next pixel line + +end: + ;; Return is included in bindings \ No newline at end of file diff --git a/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteMaskedColorizeM0_asmbindings.s b/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteMaskedColorizeM0_asmbindings.s new file mode 100644 index 000000000..1a40a3186 --- /dev/null +++ b/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteMaskedColorizeM0_asmbindings.s @@ -0,0 +1,36 @@ +;;-----------------------------LICENSE NOTICE------------------------------------ +;; This file is part of CPCtelera: An Amstrad CPC Game Engine +;; Copyright (C) 2017 Arnaud Bouche (Arnaud6128) +;; Copyright (C) 2017 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) +;; +;; This program is free software: you can redistribute it and/or modify +;; it under the terms of the GNU Lesser General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU Lesser General Public License for more details. +;; +;; You should have received a copy of the GNU Lesser General Public License +;; along with this program. If not, see <http://www.gnu.org/licenses/>. +;;------------------------------------------------------------------------------- +.module cpct_sprites + +.include "../../../macros/cpct_undocumentedOpcodes.s" + +;; +;; ASM bindings for <cpct_drawSpriteMaskedColorizeM0> +;; +cpct_drawSpriteMaskedColorizeM0_asm:: ;; Assembly entry point + + ;; GET Parameters from the stack + ld (dms_restore_ix + 2), ix ;; [6] Save IX to restore it before returning + pop hl ;; [3] HL = Return Address + +.include /cpct_drawSpriteMaskedColorizeM0.asm/ + +dms_restore_ix: + ld ix, #0000 ;; [4] Restore IX before returning + ret ;; [3] Return to caller \ No newline at end of file diff --git a/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteMaskedColorizeM0_cbindings.s b/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteMaskedColorizeM0_cbindings.s new file mode 100644 index 000000000..c39a879a4 --- /dev/null +++ b/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteMaskedColorizeM0_cbindings.s @@ -0,0 +1,48 @@ +;;-----------------------------LICENSE NOTICE------------------------------------ +;; This file is part of CPCtelera: An Amstrad CPC Game Engine +;; Copyright (C) 2017 Arnaud Bouche (Arnaud6128) +;; Copyright (C) 2017 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) +;; +;; This program is free software: you can redistribute it and/or modify +;; it under the terms of the GNU Lesser General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU Lesser General Public License for more details. +;; +;; You should have received a copy of the GNU Lesser General Public License +;; along with this program. If not, see <http://www.gnu.org/licenses/>. +;;------------------------------------------------------------------------------- +.module cpct_sprites + +.include "../../../macros/cpct_undocumentedOpcodes.s" + +;; +;; C bindings for <cpct_drawSpriteMaskedColorizeM0> +;; +;; 33 us, 13 bytes +;; +_cpct_drawSpriteMaskedColorizeM0:: + + ;; GET Parameters from the stack + ld (dms_restore_ix + 2), ix ;; [6] Save IX to restore it before returning + pop hl ;; [3] HL = Return Address + + exx + pop hl ;; [3] HL' = Source address (Sprite) + pop de ;; [3] DE' = Destination Memory + pop bc ;; [5] BC' = (B = Sprite Height, C = Width) + exx + + ex (sp), hl ;; [6] HL = (H = newColor, L = oldColor) + ;; ... and leave Return Address at (SP) as we don't need to restore + ;; ... stack status because callin convention is __z88dk_callee + +.include /cpct_drawSpriteMaskedColorizeM0.asm/ + +dms_restore_ix: + ld ix, #0000 ;; [4] Restore IX before returning + ret ;; [3] Return to caller \ No newline at end of file diff --git a/cpctelera/src/sprites/colorReplace/M0/cpct_spriteColorizeM0.asm b/cpctelera/src/sprites/colorReplace/M0/cpct_spriteColorizeM0.asm new file mode 100644 index 000000000..52f433ba3 --- /dev/null +++ b/cpctelera/src/sprites/colorReplace/M0/cpct_spriteColorizeM0.asm @@ -0,0 +1,166 @@ +;;-----------------------------LICENSE NOTICE------------------------------------ +;; This file is part of CPCtelera: An Amstrad CPC Game Engine +;; Copyright (C) 2017 Arnaud Bouche +;; Copyright (C) 2017 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) +;; +;; This program is free software: you can redistribute it and/or modify +;; it under the terms of the GNU Lesser General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU Lesser General Public License for more details. +;; +;; You should have received a copy of the GNU Lesser General Public License +;; along with this program. If not, see <http://www.gnu.org/licenses/>. +;;------------------------------------------------------------------------------- +.module cpct_sprites + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; +;; Function: cpct_spriteColorizeM0 +;; +;; Replace a color in a sprite and copy to another or the same sprite. +;; +;; C Definition: +;; void <cpct_spriteColorizeM0> (void* *sprite*, void* *spriteColor*, <u8> *width*, <u8> *height*, <u8> *oldColor*, <u8> *newColor*) __z88dk_callee; +;; +;; Input Parameters (6 bytes): +;; (2B HL') sprite - Source Sprite Pointer (array of pixel data) +;; (2B DE') spriteColor - Destination Sprite Pointer (can be also the Source Sprite) (array of pixel data) +;; (1B C' ) height - Sprite Height in bytes (>0) +;; (1B B' ) width - Sprite Width in *bytes* (Beware, *not* in pixels!) +;; (1B L ) oldColor - Color to replace +;; (1B H ) newColor - New color +;; +;; Assembly call (Input parameters on registers): +;; > call cpct_spriteColorizeM0_asm +;; +;; Parameter Restrictions: +;; * *sprite* must be an array containing sprite's pixels data in screen pixel format. +;; Sprite must be rectangular and all bytes in the array must be consecutive pixels, +;; starting from top-left corner and going left-to-right, top-to-bottom down to the +;; bottom-right corner. Total amount of bytes in pixel array should be *width* x *height*. +;; * *spriteColor* must be an array containing the new sprite's pixels data with the new color. +;; * *width* must be the width of the sprite *in bytes*. Always remember that the width must be +;; expressed in bytes and *not* in pixels. +;; The correspondence is mode 0 : 1 byte = 2 pixels +;; * *height* must be the height of the sprite in bytes, and must be greater than 0. +;; There is no practical upper limit to this value. Height of a sprite in +;; bytes and pixels is the same value, as bytes only group consecutive pixels in +;; the horizontal space. +;; * *oldColor* must be the index of color (0 to 15) to replace +;; * *newColor* must be the index of the new color (0 to 15) +;; +;; Known limitations: +;; * This function *will not work from ROM*, as it uses self-modifying code. +;; * This function requires the CPC firmware to be DISABLED. Otherwise, random crashes might happen due to side effects. +;; +;; Destroyed Register values: +;; AF, BC, DE, HL, BC', DE', HL', IX +;; +;; Required memory: +;; C-bindings - 81 bytes +;; ASM-bindings - 67 bytes +;; +;; Time Measures: +;; (start code) +;; Case | microSecs (us) | CPU Cycles +;; ---------------------------------------------------------------- +;; | 29 + (6 + 33W)H | 116 + (24 + 132W)H +;; ---------------------------------------------------------------- +;; W=2,H=16 | 1181 | 4724 +;; W=4,H=32 | 4445 | 17780 +;; ---------------------------------------------------------------- +;; Asm saving | -16 | -64 +;; ---------------------------------------------------------------- +;; (end code) +;; W = *width* in bytes, H = *height* in bytes +;; +;; Credits: +;; Original routine optimized by @Docent and discussed in CPCWiki : +;; http://www.cpcwiki.eu/forum/programming/cpctelera-colorize-sprite/ +;; +;; Thanks to all of them for their help and support. +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +.globl dc_mode0_ct + +;; Macro to convert Pixel to xAxC xBxD format +.macro convertPixel + ;; From cpct_px2byteM0 + ld bc, #dc_mode0_ct ;; [3] BC points to conversion table (dc_mode0_ct) + + ;; Compute BC += A + add c ;; [1] | C += A + ld c, a ;; [1] | + sub a ;; [1] A = 0 (preserving Carry Flag) + adc b ;; [1] | B += Carry + ld b, a ;; [1] | + + ;; A = *(BC + A) + ld a, (bc) ;; [2] A = Value stored at the table pointed by BC +.endm + + ;; Convert newColor to pixel format (E) + ld a, h ;; [1] A = H new color index + convertPixel ;; [10] | Convert into A + ld e, a ;; [1] | E = A new color : xAxC xBxD + + ;; Convert oldColor to pixel format (D) + ld a, l ;; [1] A = L old color index + convertPixel ;; [10] | Convert into A + ld d, a ;; [1] | D = A old color : xAxC xBxD + + ld c, #0x55 ;; [2] C = Mask to get pixel A : xAxC xBxD + exx ;; [1] Switch to Alternate registers + + ld__ixl_c ;; [1] IXL = C (Width) + ld c, b ;; [1] C = B (Height) + +convertLoop: + ld__b_ixl ;; [2] B = IXL (Sprite Width) + +lineLoop: + ld a, (hl) ;; [2] A = (HL) current Byte of sprite + exx ;; [1] Switch to Default registers + + ld l, a ;; [1] L = A current Byte of sprite : ABAB ABAB + and c ;; [2] A |= C (C = 0x55) : xBxB xBxB + + cp d ;; [1] Test if pixel (A) is the old colour to be replaced (D) + jr nz, readPixelA ;; [2/3] If not equal go to next pixel + ld a, e ;; [1] else A = new colour to set (E) + +;; Pixel Mode 0 = ABAB ABAB +readPixelA: + ld h, a ;; [1] H = A (current colorized sprite) : xBxB xBxB + ld a, l ;; [1] L = A current Byte of sprite : ABAB ABAB + rrca ;; [1] A (current byte of sprite) >> 1 : ABAB ABAB -> xABA BABA + and c ;; [2] A |= Mask (0x55) : xAxA xAxA + + cp d ;; [1] Test if pixel (A) is the old colour to be replaced (D) + jr nz, readPixelB ;; [2/3] If not equal go to next pixel + ld a, e ;; [1] else A = new colour to set (E) + +readPixelB: + rlca ;; [1] A = xAxA xAxA << 1 : AxAx AxAx + or h ;; [1] A |= H (xBxB xBxB) : ABAB ABAB + +setByte: + exx ;; [1] Switch to Alternate registers + + ld (de), a ;; [2] Update current sprite byte with pixels + inc hl ;; [2] Next byte sprite source + inc de ;; [2] Next byte sprite colorized + djnz lineLoop ;; [3] Decrement B (Width) if != 0 goto lineLoop + +nextLine: + dec c ;; [1] Decrement C (Height) + jr nz, convertLoop ;; [2/3] If != O goto convertLoop + +end: + ;; Return is included in bindings + diff --git a/cpctelera/src/sprites/colorReplace/M0/cpct_spriteColorizeM0_asmbindings.s b/cpctelera/src/sprites/colorReplace/M0/cpct_spriteColorizeM0_asmbindings.s new file mode 100644 index 000000000..9ac97a5e6 --- /dev/null +++ b/cpctelera/src/sprites/colorReplace/M0/cpct_spriteColorizeM0_asmbindings.s @@ -0,0 +1,36 @@ +;;-----------------------------LICENSE NOTICE------------------------------------ +;; This file is part of CPCtelera: An Amstrad CPC Game Engine +;; Copyright (C) 2017 Arnaud Bouche (Arnaud6128) +;; Copyright (C) 2017 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) +;; +;; This program is free software: you can redistribute it and/or modify +;; it under the terms of the GNU Lesser General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU Lesser General Public License for more details. +;; +;; You should have received a copy of the GNU Lesser General Public License +;; along with this program. If not, see <http://www.gnu.org/licenses/>. +;;------------------------------------------------------------------------------- +.module cpct_sprites + +.include "../../../macros/cpct_undocumentedOpcodes.s" + +;; +;; ASM bindings for <cpct_spriteColorizeM0> +;; +cpct_spriteColorizeM0_asm:: ;; Assembly entry point + + ;; GET Parameters from the stack + ld (dms_restore_ix + 2), ix ;; [6] Save IX to restore it before returning + pop hl ;; [3] HL = Return Address + +.include /cpct_spriteColorizeM0.asm/ + +dms_restore_ix: + ld ix, #0000 ;; [4] Restore IX before returning + ret ;; [3] Return to caller \ No newline at end of file diff --git a/cpctelera/src/sprites/colorReplace/M0/cpct_spriteColorizeM0_cbindings.s b/cpctelera/src/sprites/colorReplace/M0/cpct_spriteColorizeM0_cbindings.s new file mode 100644 index 000000000..f31436707 --- /dev/null +++ b/cpctelera/src/sprites/colorReplace/M0/cpct_spriteColorizeM0_cbindings.s @@ -0,0 +1,48 @@ +;;-----------------------------LICENSE NOTICE------------------------------------ +;; This file is part of CPCtelera: An Amstrad CPC Game Engine +;; Copyright (C) 2017 Arnaud Bouche +;; Copyright (C) 2017 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) +;; +;; This program is free software: you can redistribute it and/or modify +;; it under the terms of the GNU Lesser General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU Lesser General Public License for more details. +;; +;; You should have received a copy of the GNU Lesser General Public License +;; along with this program. If not, see <http://www.gnu.org/licenses/>. +;;------------------------------------------------------------------------------- +.module cpct_sprites + +.include "../../../macros/cpct_undocumentedOpcodes.s" + +;; +;; C bindings for <cpct_spriteColorizeM0> +;; +;; 33 us, 14 bytes +;; +_cpct_spriteColorizeM0:: + + ;; GET Parameters from the stack + ld (dms_restore_ix + 2), ix ;; [6] Save IX to restore it before returning + pop hl ;; [3] HL = Return Address + + exx + pop hl ;; [3] HL' = Source address (Sprite) + pop de ;; [3] DE' = Destination Sprite color + pop bc ;; [5] BC' = (B = Sprite Height, C = Width) + exx + + ex (sp), hl ;; [6] HL = (H = newColor, L = oldColor) + ;; ... and leave Return Address at (SP) as we don't need to restore + ;; ... stack status because callin convention is __z88dk_callee + +.include /cpct_spriteColorizeM0.asm/ + +dms_restore_ix: + ld ix, #0000 ;; [4] Restore IX before returning + ret ;; [3] Return to caller \ No newline at end of file diff --git a/cpctelera/src/sprites/colorReplace/M0/cpct_spriteMaskedColorizeM0.asm b/cpctelera/src/sprites/colorReplace/M0/cpct_spriteMaskedColorizeM0.asm new file mode 100644 index 000000000..d6662e5c2 --- /dev/null +++ b/cpctelera/src/sprites/colorReplace/M0/cpct_spriteMaskedColorizeM0.asm @@ -0,0 +1,175 @@ +;;-----------------------------LICENSE NOTICE------------------------------------ +;; This file is part of CPCtelera: An Amstrad CPC Game Engine +;; Copyright (C) 2017 Arnaud Bouche (Arnaud6128) +;; Copyright (C) 2017 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) +;; +;; This program is free software: you can redistribute it and/or modify +;; it under the terms of the GNU Lesser General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU Lesser General Public License for more details. +;; +;; You should have received a copy of the GNU Lesser General Public License +;; along with this program. If not, see <http://www.gnu.org/licenses/>. +;;------------------------------------------------------------------------------- +.module cpct_sprites + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; +;; Function: cpct_spriteMaskedColorizeM0 +;; +;; Replace a color in a Masked sprite and copy to another or the same sprite. +;; +;; C Definition: +;; void <cpct_spriteMaskedColorizeM0> (void* *sprite*, void* *spriteColor*, <u8> *width*, <u8> *height*, <u8> *oldColor*, <u8> *newColor*) __z88dk_callee; +;; +;; Input Parameters (6 bytes): +;; (2B HL') sprite - Source Sprite Pointer (array of pixel data) +;; (2B DE') spriteColor - Destination Sprite Pointer (can be also the Source Sprite) (array of pixel data) +;; (1B C') height - Sprite Height in bytes (>0) +;; (1B B') width - Sprite Width in *bytes* (Beware, *not* in pixels!) +;; (1B L) oldColor - Color to replace +;; (1B H) newColor - New color +;; +;; Assembly call (Input parameters on registers): +;; > call cpct_spriteMaskedColorizeM0_asm +;; +;; Parameter Restrictions: +;; * *sprite* must be an array containing sprite's pixels data in screen pixel format +;; along with mask data. Each mask byte will contain enabled bits as those that should +;; be picked from the background (transparent) and disabled bits for those that will +;; be printed from sprite colour data. Each mask data byte must precede its associated +;; colour data byte. +;; Sprite must be rectangular and all bytes in the array must be consecutive pixels, +;; starting from top-left corner and going left-to-right, top-to-bottom down to the +;; bottom-right corner. Total amount of bytes in pixel array should be +;; 2 x *width* x *height* (mask data doubles array size). +;; * *spriteColor* must be an array containing the new sprite's pixels data with the new color. +;; Total amount of bytes in pixel array should be 2 x *width* x *height* (mask data doubles array size). +;; * *width* must be the width of the sprite *in bytes*. Always remember that the width must be +;; expressed in bytes and *not* in pixels. +;; The correspondence is mode 0 : 1 byte = 2 pixels +;; * *height* must be the height of the sprite in bytes, and must be greater than 0. +;; There is no practical upper limit to this value. Height of a sprite in +;; bytes and pixels is the same value, as bytes only group consecutive pixels in +;; the horizontal space. +;; * *oldColor* must be the index of color (0 to 15) to replace +;; * *newColor* must be the index of the new color (0 to 15) +;; +;; Known limitations: +;; * This function *will not work from ROM*, as it uses self-modifying code. +;; * This function requires the CPC firmware to be DISABLED. Otherwise, random crashes might happen due to side effects. +;; +;; Destroyed Register values: +;; AF, BC, DE, HL, BC', DE', HL', IX +;; +;; Required memory: +;; C-bindings - 87 bytes +;; ASM-bindings - 73 bytes +;; +;; Time Measures: +;; (start code) +;; Case | microSecs (us) | CPU Cycles +;; ---------------------------------------------------------------- +;; | 29 + (41 + 6W)H | 116 + (164 + 24W)H +;; ---------------------------------------------------------------- +;; W=2,H=16 | 2109 | 8436 +;; W=4,H=32 | 877 | 3508 +;; ---------------------------------------------------------------- +;; Asm saving | -16 | -64 +;; ---------------------------------------------------------------- +;; (end code) +;; W = *width* in bytes, H = *height* in bytes, HH = [(H-1)/8] +;; +;; Credits: +;; Original routine optimized by @Docent and discussed in CPCWiki : +;; http://www.cpcwiki.eu/forum/programming/cpctelera-colorize-sprite/ +;; +;; Thanks to all of them for their help and support. +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +.globl dc_mode0_ct + +;; Macro to convert Pixel to xAxC xBxD format +.macro convertPixel + ;; From cpct_px2byteM0 + ld bc, #dc_mode0_ct ;; [3] BC points to conversion table (dc_mode0_ct) + + ;; Compute BC += A + add c ;; [1] | C += A + ld c, a ;; [1] | + sub a ;; [1] A = 0 (preserving Carry Flag) + adc b ;; [1] | B += Carry + ld b, a ;; [1] | + + ;; A = *(BC + A) + ld a, (bc) ;; [2] A = Value stored at the table pointed by BC +.endm + + ;; Convert newColor to pixel format (E) + ld a, h ;; [1] A = H new color index + convertPixel ;; [10] | Convert into A + ld e, a ;; [1] | E = A new color : xAxC xBxD + + ;; Convert oldColor to pixel format (D) + ld a, l ;; [1] A = L old color index + convertPixel ;; [10] | Convert into A + ld d, a ;; [1] | D = A old color : xAxC xBxD + + ld c, #0x55 ;; [2] C = Mask to get pixel A : xAxC xBxD + exx ;; [1] Switch to Alternate registers + + ld__ixl_c ;; [1] IXL = C (Width) + ld c, b ;; [1] C = B (Height) + +convertLoop: + ld__b_ixl ;; [2] B = IXL (Sprite Width) + +lineLoop: + ld a, (hl) ;; [2] A = (HL) current Byte of sprite Mask + ld (de), a ;; [2] (DE) = A Copy of sprite Mask + inc hl ;; [2] Next byte sprite Color source + inc de ;; [2] Next byte sprite Color destination + ld a, (hl) ;; [2] A = (HL) current Byte of sprite Color + + exx ;; [1] Switch to Default registers + + ld l, a ;; [1] L = A current Byte of sprite : ABAB ABAB + and c ;; [2] A |= C (C = 0x55) : xBxB xBxB + + cp d ;; [1] Test if pixel (A) is the old colour to be replaced (D) + jr nz, readPixelA ;; [2/3] If not equal go to next pixel + ld a, e ;; [1] else A = new colour to set (E) + +;; Pixel Mode 0 = ABAB ABAB +readPixelA: + ld h, a ;; [1] H = A (current colorized sprite) : xBxB xBxB + ld a, l ;; [1] L = A current Byte of sprite : ABAB ABAB + rrca ;; [1] A (current byte of sprite) >> 1 : ABAB ABAB -> xABA BABA + and c ;; [2] A |= Mask (0x55) : xAxA xAxA + + cp d ;; [1] Test if pixel (A) is the old colour to be replaced (D) + jr nz, readPixelB ;; [2/3] If not equal go to next pixel + ld a, e ;; [1] else A = new colour to set (E) + +readPixelB: + rlca ;; [1] A = xAxA xAxA << 1 : AxAx AxAx + or h ;; [1] A |= H (xBxB xBxB) : ABAB ABAB + +setByte: + exx ;; [1] Switch to Alternate registers + + ld (de), a ;; [2] Update current sprite byte with pixels + inc hl ;; [2] Next byte sprite source + inc de ;; [2] Next byte sprite colorized + djnz lineLoop ;; [3] Decrement B (Width) if != 0 goto lineLoop + + dec c ;; [1] Decrement C (Height) + jr nz, convertLoop ;; [2/3] If C == O goto end + +end: + ;; Return is included in bindings \ No newline at end of file diff --git a/cpctelera/src/sprites/colorReplace/M0/cpct_spriteMaskedColorizeM0_asmbindings.s b/cpctelera/src/sprites/colorReplace/M0/cpct_spriteMaskedColorizeM0_asmbindings.s new file mode 100644 index 000000000..30440d708 --- /dev/null +++ b/cpctelera/src/sprites/colorReplace/M0/cpct_spriteMaskedColorizeM0_asmbindings.s @@ -0,0 +1,36 @@ +;;-----------------------------LICENSE NOTICE------------------------------------ +;; This file is part of CPCtelera: An Amstrad CPC Game Engine +;; Copyright (C) 2017 Arnaud Bouche (Arnaud6128) +;; Copyright (C) 2017 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) +;; +;; This program is free software: you can redistribute it and/or modify +;; it under the terms of the GNU Lesser General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU Lesser General Public License for more details. +;; +;; You should have received a copy of the GNU Lesser General Public License +;; along with this program. If not, see <http://www.gnu.org/licenses/>. +;;------------------------------------------------------------------------------- +.module cpct_sprites + +.include "../../../macros/cpct_undocumentedOpcodes.s" + +;; +;; ASM bindings for <cpct_spriteMaskedColorizeM0> +;; +cpct_spriteMaskedColorizeM0_asm:: ;; Assembly entry point + + ;; GET Parameters from the stack + ld (dms_restore_ix + 2), ix ;; [6] Save IX to restore it before returning + pop hl ;; [3] HL = Return Address + +.include /cpct_spriteMaskedColorizeM0.asm/ + +dms_restore_ix: + ld ix, #0000 ;; [4] Restore IX before returning + ret ;; [3] Return to caller \ No newline at end of file diff --git a/cpctelera/src/sprites/colorReplace/M0/cpct_spriteMaskedColorizeM0_cbindings.s b/cpctelera/src/sprites/colorReplace/M0/cpct_spriteMaskedColorizeM0_cbindings.s new file mode 100644 index 000000000..a2bba9de5 --- /dev/null +++ b/cpctelera/src/sprites/colorReplace/M0/cpct_spriteMaskedColorizeM0_cbindings.s @@ -0,0 +1,48 @@ +;;-----------------------------LICENSE NOTICE------------------------------------ +;; This file is part of CPCtelera: An Amstrad CPC Game Engine +;; Copyright (C) 2017 Arnaud Bouche (Arnaud6128) +;; Copyright (C) 2017 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) +;; +;; This program is free software: you can redistribute it and/or modify +;; it under the terms of the GNU Lesser General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU Lesser General Public License for more details. +;; +;; You should have received a copy of the GNU Lesser General Public License +;; along with this program. If not, see <http://www.gnu.org/licenses/>. +;;------------------------------------------------------------------------------- +.module cpct_sprites + +.include "../../../macros/cpct_undocumentedOpcodes.s" + +;; +;; C bindings for <cpct_spriteMaskedColorizeM0> +;; +;; 33 us, 14 bytes +;; +_cpct_spriteMaskedColorizeM0:: + + ;; GET Parameters from the stack + ld (dms_restore_ix + 2), ix ;; [6] Save IX to restore it before returning + pop hl ;; [3] HL = Return Address + + exx + pop hl ;; [3] HL' = Source address (Sprite) + pop de ;; [3] DE' = Destination Sprite color + pop bc ;; [5] BC' = (B = Sprite Height, C = Width) + exx + + ex (sp), hl ;; [6] HL = (H = newColor, L = oldColor) + ;; ... and leave Return Address at (SP) as we don't need to restore + ;; ... stack status because callin convention is __z88dk_callee + +.include /cpct_spriteMaskedColorizeM0.asm/ + +dms_restore_ix: + ld ix, #0000 ;; [4] Restore IX before returning + ret ;; [3] Return to caller \ No newline at end of file diff --git a/cpctelera/src/sprites/colorReplace/M1/cpct_drawSpriteColorizeM1.asm b/cpctelera/src/sprites/colorReplace/M1/cpct_drawSpriteColorizeM1.asm new file mode 100644 index 000000000..c6b6b8614 --- /dev/null +++ b/cpctelera/src/sprites/colorReplace/M1/cpct_drawSpriteColorizeM1.asm @@ -0,0 +1,228 @@ +;;-----------------------------LICENSE NOTICE------------------------------------ +;; This file is part of CPCtelera: An Amstrad CPC Game Engine +;; Copyright (C) 2017 Arnaud Bouche (Arnaud6128) +;; Copyright (C) 2017 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) +;; +;; This program is free software: you can redistribute it and/or modify +;; it under the terms of the GNU Lesser General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU Lesser General Public License for more details. +;; +;; You should have received a copy of the GNU Lesser General Public License +;; along with this program. If not, see <http://www.gnu.org/licenses/>. +;;------------------------------------------------------------------------------- +.module cpct_sprites + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; +;; Function: cpct_drawSpriteColorizeM1 +;; +;; Directly replace a color and draw a sprite to video memory. +;; +;; C Definition: +;; void <cpct_drawSpriteColorizeM1> (void* *sprite*, void* *memory*, <u8> *width*, <u8> *height*, <u8> *oldColor*, <u8> *newColor*) __z88dk_callee; +;; +;; Input Parameters (6 bytes): +;; (2B HL') sprite - Source Sprite Pointer (array of pixel data) +;; (2B DE') memory - Destination video memory pointer +;; (1B C' ) height - Sprite Height in bytes (>0) +;; (1B B' ) width - Sprite Width in *bytes* (Beware, *not* in pixels!) +;; (1B L ) oldColor - Color to replace +;; (1B H ) newColor - New color +;; +;; Assembly call (Input parameters on registers): +;; > call cpct_drawSpriteColorizeM1_asm +;; +;; Parameter Restrictions: +;; * *sprite* must be an array containing sprite's pixels data in screen pixel format. +;; Sprite must be rectangular and all bytes in the array must be consecutive pixels, +;; starting from top-left corner and going left-to-right, top-to-bottom down to the +;; bottom-right corner. Total amount of bytes in pixel array should be *width* x *height*. +;; * *memory* could be any place in memory, inside or outside current video memory. It +;; will be equally treated as video memory (taking into account CPC's video memory +;; disposition). This lets you copy sprites to software or hardware backbuffers, and +;; not only video memory. +;; * *width* must be the width of the sprite *in bytes*. Always remember that the width must be +;; expressed in bytes and *not* in pixels. +;; The correspondence is mode 1 : 1 byte = 4 pixels +;; * *height* must be the height of the sprite in bytes, and must be greater than 0. +;; There is no practical upper limit to this value. Height of a sprite in +;; bytes and pixels is the same value, as bytes only group consecutive pixels in +;; the horizontal space. +;; * *oldColor* must be the index of color (0 to 3) to replace +;; * *newColor* must be the index of the new color (0 to 3) +;; +;; Known limitations: +;; * This function does not do any kind of boundary check or clipping. If you +;; try to draw sprites on the frontier of your video memory or screen buffer +;; if might potentially overwrite memory locations beyond boundaries. This +;; could cause your program to behave erratically, hang or crash. Always +;; take the necessary steps to guarantee that you are drawing inside screen +;; or buffer boundaries. +;; * As this function receives a byte-pointer to memory, it can only +;; draw byte-sized and byte-aligned sprites. This means that the box cannot +;; start on non-byte aligned pixels (like odd-pixels, for instance) and +;; their sizes must be a multiple of a byte (2 in mode 0, 4 in mode 1 and +;; 8 in mode 2). +;; * This function *will not work from ROM*, as it uses self-modifying code. +;; * This function requires the CPC firmware to be DISABLED. Otherwise, random crashes might happen due to side effects. +;; +;; Destroyed Register values: +;; AF, BC, DE, HL, BC', DE', HL', IX +;; +;; Required memory: +;; C-bindings - 116 bytes +;; ASM-bindings - 103 bytes +;; +;; Time Measures: +;; (start code) +;; Case | microSecs (us) | CPU Cycles +;; ---------------------------------------------------------------- +;; | 29 + (36 + 61W)H | 116 + (144 + 244W)H +;; ---------------------------------------------------------------- +;; W=2,H=16 | 2557 | 10228 +;; W=4,H=32 | 8989 | 35956 +;; ---------------------------------------------------------------- +;; Asm saving | -16 | -64 +;; ---------------------------------------------------------------- +;; (end code) +;; W = *width* in bytes, H = *height* in bytes +;; +;; Credits: +;; Original routine optimized by @Docent and discussed in CPCWiki : +;; http://www.cpcwiki.eu/forum/programming/cpctelera-colorize-sprite/ +;; +;; Thanks to all of them for their help and support. +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +.globl dc_mode1_ct + +;; Macro to convert color to pixel Mode1 : Axxx Axxx +.macro convertPixel ;; From cpct_px2byteM1 + ld bc, #dc_mode1_ct ;; [3] BC points to conversion table (dc_mode1_ct) + + ;; Compute BC += A + add c ;; [1] | C += A + ld c, a ;; [1] | + sub a ;; [1] A = 0 (preserving Carry Flag) + adc b ;; [1] | B += Carry + ld b, a ;; [1] | + + ;; A = *(BC + A) + ld a, (bc) ;; [2] A = Value stored at the table pointed by BC +.endm + + ;; Convert newColor to pixel format (E) + ld a, h ;; [1] A = H new color index + convertPixel ;; [10] | Convert into A + ld e, a ;; [1] | E = A new color : Axxx Axxx + + ;; Convert oldColor to pixel format (D) + ld a, l ;; [1] A = L old color index + convertPixel ;; [10] | Convert into A + ld d, a ;; [1] | D = A old color : Axxx Axxx + + ld c, #0x88 ;; [2] C = Mask to get pixel A : Axxx Axxx + exx ;; [1] Switch to Alternate registers + + ld__ixl_c ;; [1] IXL = C (Width) + ld c, b ;; [1] C = B (Height) + +convertLoop: + ld (startLine), de ;; [6] Store DE start line (DestMem) + ld__b_ixl ;; [2] B = IXL (Sprite Width) + +lineLoop: + ld a, (hl) ;; [2] A = (HL) current Byte of sprite + exx ;; [1] Switch to Default registers + + ld l, a ;; [1] L = A current Byte of sprite : ABCD ABCD + and c ;; [2] A |= C (C = 0x88) : Axxx Axxx + + cp d ;; [1] Test if pixel (A) is the old colour to be replaced (D) + jr nz, readPixelA ;; [2/3] If not equal go to next pixel + ld a, e ;; [1] else A = new colour to set (E) + +readPixelA: + ld h, a ;; [1] H = A (current colorized sprite) : Axxx Axxx + + sla l ;; [2] L (current byte of sprite) << 1 : ABCD ABCD -> BCDx BCDx + ld a, l ;; [1] A = L : BCDx BCDx + and c ;; [2] A |= Mask (0x88) : Bxxx Bxxx + + cp d ;; [1] Test if pixel (A) is the old colour to be replaced (D) + jr nz, readPixelB ;; [2/3] If not equal go to next pixel + ld a, e ;; [1] else A = new colour to set (E) + +readPixelB: + rrca ;; [1] A = Axxx Axxx >> 1 : xBxx xBxx + or h ;; [1] A |= H (color byte) : Axxx Axxx + ld h, a ;; [1] H = A : ABxx ABxx + + sla l ;; [2] L ( BCDx BCDx) << 1 : CDxx CDxx + ld a, l ;; [1] A = L : CDxx CDxx + and c ;; [1] A |= C (C = 0x88) : Cxxx Cxxx + + cp d ;; [1] Test if pixel (A) is the old colour to be replaced (D) + jr nz, readPixelC ;; [2/3] If not equal go to next pixel + ld a, e ;; [1] else A = new colour to set (E) + +readPixelC: + rrca ;; [1] A = Axxx Axxx >> 1 : xBxx xBxx + rrca ;; [1] A = xxCx xxCx << 1 : xxCx xxCx + or h ;; [1] A |= H (ABxx ABxx) : ABCx ABCx + ld h, a ;; [1] H = A : ABCx ABCx + + sla l ;; [2] L (BCDx BCDx) << 1 : Dxxx Dxxx + ld a, l ;; [1] A = L : Dxxx Dxxx + and c ;; [1] A |= C (C = 0x88) : Dxxx Dxxx + + cp d ;; [1] Test if pixel (A) is the old colour to be replaced (D) + jr nz, readPixelD ;; [2/3] If not equal go to next pixel + ld a, e ;; [1] else A = new colour to set (E) + +readPixelD: + rrca ;; [1] A = Axxx Axxx >> 1 : xBxx xBxx + rrca ;; [1] A = xBxx xBxx >> 1 : xxCx xxCx + rrca ;; [1] A = xxCx xxxx >> 1 : xxxD xxxD + or h ;; [1] A |= H (ABCx ABCx) : ABCD ABCD + + exx ;; [1] Switch to Alternate registers + + ld (de), a ;; [2] Update current sprite byte with pixels + inc hl ;; [2] Next byte sprite source + inc de ;; [2] Next byte sprite colorized + djnz lineLoop ;; [3] Decrement B (Width) if B != 0 goto lineLoop + + dec c ;; [1] Decrement C (Height) + jr z, end ;; [2/3] If C == O goto end + +startLine = .+1 ;; Placeholder for the Start line adress + ld de, #0000 ;; [3] DE = Start Line + + ld a, d ;; [1] Start of next pixel line normally is 0x0800 bytes away. + add #0x08 ;; [2] so we add it to DE (just by adding 0x08 to D) + ld d, a ;; [1] + and #0x38 ;; [2] We check if we have crossed memory boundary (every 8 pixel lines).. + + jr nz, convertLoop ;; [2/3] .. by checking the 4 bits that identify present memory line. + ;; .... If 0, we have crossed boundaries + +dms_sprite_8bit_boundary_crossed: + ld a, e ;; [1] DE = DE + 0xC050h + add #0x50 ;; [2] -- Relocate DE pointer to the start of the next pixel line: + ld e, a ;; [1] -- DE is moved forward 3 memory banks plus 50 bytes (4000h * 3) + ld a, d ;; [1] -- which effectively is the same as moving it 1 bank backwards and then + adc #0xC0 ;; [2] -- 50 bytes forwards (which is what we want to move it to the next pixel line) + ld d, a ;; [1] -- Calculations are made with 8 bit maths as it is faster than other alternatives here + + jr convertLoop ;; [3] Jump to continue with next pixel line + +end: + ;; Return is included in bindings + diff --git a/cpctelera/src/sprites/colorReplace/M1/cpct_drawSpriteColorizeM1_asmbindings.s b/cpctelera/src/sprites/colorReplace/M1/cpct_drawSpriteColorizeM1_asmbindings.s new file mode 100644 index 000000000..44ca0f2b0 --- /dev/null +++ b/cpctelera/src/sprites/colorReplace/M1/cpct_drawSpriteColorizeM1_asmbindings.s @@ -0,0 +1,35 @@ +;;-----------------------------LICENSE NOTICE------------------------------------ +;; This file is part of CPCtelera: An Amstrad CPC Game Engine +;; Copyright (C) 2017 Arnaud Bouche (Arnaud6128) +;; Copyright (C) 2017 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) +;; +;; This program is free software: you can redistribute it and/or modify +;; it under the terms of the GNU Lesser General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU Lesser General Public License for more details. +;; +;; You should have received a copy of the GNU Lesser General Public License +;; along with this program. If not, see <http://www.gnu.org/licenses/>. +;;------------------------------------------------------------------------------- +.module cpct_sprites + +.include "../../../macros/cpct_undocumentedOpcodes.s" + +;; +;; ASM bindings for <cpct_drawSpriteColorizeM1> +;; +cpct_drawSpriteColorizeM1_asm:: ;; Assembly entry point + +;; GET Parameters from the stack +ld (dms_restore_ix + 2), ix ;; [6] Save IX to restore it before returning + +.include /cpct_drawSpriteColorizeM1.asm/ + +dms_restore_ix: + ld ix, #0000 ;; [4] Restore IX before returning + ret \ No newline at end of file diff --git a/cpctelera/src/sprites/colorReplace/M1/cpct_drawSpriteColorizeM1_cbindings.s b/cpctelera/src/sprites/colorReplace/M1/cpct_drawSpriteColorizeM1_cbindings.s new file mode 100644 index 000000000..22798d0f3 --- /dev/null +++ b/cpctelera/src/sprites/colorReplace/M1/cpct_drawSpriteColorizeM1_cbindings.s @@ -0,0 +1,48 @@ +;;-----------------------------LICENSE NOTICE------------------------------------ +;; This file is part of CPCtelera: An Amstrad CPC Game Engine +;; Copyright (C) 2017 Arnaud Bouche (Arnaud6128) +;; Copyright (C) 2017 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) +;; +;; This program is free software: you can redistribute it and/or modify +;; it under the terms of the GNU Lesser General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU Lesser General Public License for more details. +;; +;; You should have received a copy of the GNU Lesser General Public License +;; along with this program. If not, see <http://www.gnu.org/licenses/>. +;;------------------------------------------------------------------------------- +.module cpct_sprites + +.include "../../../macros/cpct_undocumentedOpcodes.s" + +;; +;; C bindings for <cpct_drawSpriteColorizeM1> +;; +;; 31 us, 13 bytes +;; +_cpct_drawSpriteColorizeM1:: + + ;; GET Parameters from the stack + ld (dms_restore_ix + 2), ix ;; [6] Save IX to restore it before returning + pop hl ;; [3] HL = Return Address + + exx + pop hl ;; [3] HL' = Source address (Sprite) + pop de ;; [3] DE' = Destination Memory + pop bc ;; [5] BC' = (B = Sprite Height, C = Width) + exx + + ex (sp), hl ;; [6] HL = (H = newColor, L = oldColor) + ;; ... and leave Return Address at (SP) as we don't need to restore + ;; ... stack status because callin convention is __z88dk_callee + +.include /cpct_drawSpriteColorizeM1.asm/ + +dms_restore_ix: + ld ix, #0000 ;; [4] Restore IX before returning + ret ;; [3] Return to caller \ No newline at end of file diff --git a/cpctelera/src/sprites/colorReplace/M1/cpct_drawSpriteMaskedAlignedColorizeM1.asm b/cpctelera/src/sprites/colorReplace/M1/cpct_drawSpriteMaskedAlignedColorizeM1.asm new file mode 100644 index 000000000..cbb50cdb3 --- /dev/null +++ b/cpctelera/src/sprites/colorReplace/M1/cpct_drawSpriteMaskedAlignedColorizeM1.asm @@ -0,0 +1,239 @@ +;;-----------------------------LICENSE NOTICE------------------------------------ +;; This file is part of CPCtelera: An Amstrad CPC Game Engine +;; Copyright (C) 2017 Arnaud Bouche (Arnaud6128) +;; Copyright (C) 2017 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) +;; +;; This program is free software: you can redistribute it and/or modify +;; it under the terms of the GNU Lesser General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU Lesser General Public License for more details. +;; +;; You should have received a copy of the GNU Lesser General Public License +;; along with this program. If not, see <http://www.gnu.org/licenses/>. +;;------------------------------------------------------------------------------- +.module cpct_sprites + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; +;; Function: cpct_drawSpriteMaskedAlignedColorizeM1 +;; +;; Directly replace a color and draw a sprite Masked Aligned to video memory. +;; +;; C Definition: +;; void <cpct_drawSpriteMaskedAlignedColorizeM1> (void* *sprite*, void* *memory*, <u8> *width*, <u8> *height*, +;; <u8> *oldColor*, <u8> *newColor*, <u8*> *pmasktable*) __z88dk_callee; +;; +;; Input Parameters (10 bytes): +;; (2B HL') sprite - Source Sprite Pointer (array of pixel data) +;; (2B DE') memory - Destination video memory pointer +;; (1B C' ) height - Sprite Height in bytes (>0) +;; (1B B' ) width - Sprite Width in *bytes* (Beware, *not* in pixels!) +;; (1B E ) oldColor - Color to replace +;; (1B D ) newColor - New color +;; (2B HL) pmasktable - Pointer to the aligned mask table used to create transparency +;; +;; Assembly call (Input parameters on registers): +;; > call cpct_drawSpriteMaskedAlignedColorizeM1_asm +;; +;; Parameter Restrictions: +;; * *sprite* must be an array containing sprite's pixels data in screen pixel format +;; Sprite must be rectangular and all bytes in the array must be consecutive pixels, +;; starting from top-left corner and going left-to-right, top-to-bottom down to the +;; bottom-right corner. Total amount of bytes in pixel array should be *width* x *height*. +;; * *memory* could be any place in memory, inside or outside current video memory. It +;; will be equally treated as video memory (taking into account CPC's video memory +;; disposition). This lets you copy sprites to software or hardware backbuffers, and +;; not only video memory. +;; * *width* must be the width of the sprite *in bytes*. Always remember that the width must be +;; expressed in bytes and *not* in pixels. +;; The correspondence is mode 0 : 1 byte = 4 pixels +;; * *height* must be the height of the sprite in bytes, and must be greater than 0. +;; There is no practical upper limit to this value. Height of a sprite in +;; bytes and pixels is the same value, as bytes only group consecutive pixels in +;; the horizontal space. +;; * *oldColor* must be the index of color (0 to 3) to replace +;; * *newColor* must be the index of the new color (0 to 3) +;; +;; Known limitations: +;; * This function does not do any kind of boundary check or clipping. If you +;; try to draw sprites on the frontier of your video memory or screen buffer +;; if might potentially overwrite memory locations beyond boundaries. This +;; could cause your program to behave erratically, hang or crash. Always +;; take the necessary steps to guarantee that you are drawing inside screen +;; or buffer boundaries. +;; * As this function receives a byte-pointer to memory, it can only +;; draw byte-sized and byte-aligned sprites. This means that the box cannot +;; start on non-byte aligned pixels (like odd-pixels, for instance) and +;; their sizes must be a multiple of a byte (2 in mode 0, 4 in mode 1 and +;; 8 in mode 2). +;; * This function *will not work from ROM*, as it uses self-modifying code. +;; * This function requires the CPC firmware to be DISABLED. Otherwise, random crashes might happen due to side effects. +;; +;; Destroyed Register values: +;; AF, BC, DE, HL, BC', DE', HL', IX +;; +;; Required memory: +;; C-bindings - 133 bytes +;; ASM-bindings - 117 bytes +;; +;; Time Measures: +;; (start code) +;; Case | microSecs (us) | CPU Cycles +;; ---------------------------------------------------------------- +;; | 32 + (33 + 75W)H | 128 + (132 + 300W)H +;; ---------------------------------------------------------------- +;; W=2,H=16 | 2960 | 11840 +;; W=4,H=32 | 10688 | 42752 +;; ---------------------------------------------------------------- +;; Asm saving | -16 | -64 +;; ---------------------------------------------------------------- +;; (end code) +;; W = *width* in bytes, H = *height* in bytes, HH = [(H-1)/8] +;; +;; Credits: +;; Original routine optimized by @Docent and discussed in CPCWiki : +;; http://www.cpcwiki.eu/forum/programming/cpctelera-colorize-sprite/ +;; +;; Thanks to all of them for their help and support. +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +.globl dc_mode1_ct + +;; Macro to convert color to pixel Mode1 : Axxx Axxx +.macro convertPixel ;; From cpct_px2byteM1 + ld bc, #dc_mode1_ct ;; [3] BC points to conversion table (dc_mode1_ct) + + ;; Compute BC += A + add c ;; [1] | C += A + ld c, a ;; [1] | + sub a ;; [1] A = 0 (preserving Carry Flag) + adc b ;; [1] | B += Carry + ld b, a ;; [1] | + + ;; A = *(BC + A) + ld a, (bc) ;; [2] A = Value stored at the table pointed by HL +.endm + + ;; Convert newColor to pixel format (E) + ld a, h ;; [1] A = H new color index + convertPixel ;; [10] | Convert into A + ld e, a ;; [1] | E = A new color : Axxx Axxx + + ;; Convert oldColor to pixel format (D) + ld a, l ;; [1] A = L old color index + convertPixel ;; [10] | Convert into A + ld d, a ;; [1] | D = A old color : Axxx Axxx + + ld c, #0x88 ;; [2] C = Mask to get pixel A : Axxx Axxx + exx ;; [1] Switch to Alternate registers + + ld__ixl_c ;; [1] IXL = C (Width) + ld c, b ;; [1] C = B (Height) + +convertLoop: + push de ;; [4] Store DE start line (DestMem) + ld__b_ixl ;; [2] B = IXL (Sprite Width) + +lineLoop: + ld a, (hl) ;; [2] A = (HL) current Byte of sprite Mask + exx ;; [1] Switch to Default registers + + ld l, a ;; [1] L = A current Byte of sprite : ABCD ABCD + and c ;; [2] A |= C (C = 0x88) : Axxx Axxx + + cp d ;; [1] Test if pixel (A) is the old colour to be replaced (D) + jr nz, readPixelA ;; [2/3] If not equal go to next pixel + ld a, e ;; [1] else A = new colour to set (E) + +readPixelA: + ld h, a ;; [1] H = A (current colorized sprite) : Axxx Axxx + + sla l ;; [2] L (current byte of sprite) << 1 : ABCD ABCD -> BCDx BCDx + ld a, l ;; [1] A = L : BCDx BCDx + and c ;; [2] A |= Mask (0x88) : Bxxx Bxxx + + cp d ;; [1] Test if pixel (A) is the old colour to be replaced (D) + jr nz, readPixelB ;; [2/3] If not equal go to next pixel + ld a, e ;; [1] else A = new colour to set (E) + +readPixelB: + rrca ;; [1] A = Axxx Axxx >> 1 : xBxx xBxx + or h ;; [1] A |= H (color byte) : Axxx Axxx + ld h, a ;; [1] H = A : ABxx ABxx + + sla l ;; [2] L ( BCDx BCDx) << 1 : CDxx CDxx + ld a, l ;; [1] A = L : CDxx CDxx + and c ;; [1] A |= C (C = 0x88) : Cxxx Cxxx + + cp d ;; [1] Test if pixel (A) is the old colour to be replaced (D) + jr nz, readPixelC ;; [2/3] If not equal go to next pixel + ld a, e ;; [1] else A = new colour to set (E) + +readPixelC: + rrca ;; [1] A = Axxx Axxx >> 1 : xBxx xBxx + rrca ;; [1] A = xxCx xxCx << 1 : xxCx xxCx + or h ;; [1] A |= H (ABxx ABxx) : ABCx ABCx + ld h, a ;; [1] H = A : ABCx ABCx + + sla l ;; [2] L (BCDx BCDx) << 1 : Dxxx Dxxx + ld a, l ;; [1] A = L : Dxxx Dxxx + and c ;; [1] A |= C (C = 0x88) : Dxxx Dxxx + + cp d ;; [1] Test if pixel (A) is the old colour to be replaced (D) + jr nz, readPixelD ;; [2/3] If not equal go to next pixel + ld a, e ;; [1] else A = new colour to set (E) + +readPixelD: + rrca ;; [1] A = Axxx Axxx >> 1 : xBxx xBxx + rrca ;; [1] A = xBxx xBxx >> 1 : xxCx xxCx + rrca ;; [1] A = xxCx xxxx >> 1 : xxxD xxxD + or h ;; [1] A |= H (ABCx ABCx) : ABCD ABCD + + exx ;; [1] Switch to Alternate registers + +drawByte: + push hl ;; [4] Store HL (current byte sprite source) + ld h, b ;; [1] H = B (Masked table adress High Byte) + ld l, a ;; [1] Access mask table element (table must be 256-byte aligned) + ld a, (de) ;; [2] Get the value of the byte of the screen where we are going to draw + and (hl) ;; [2] Erase background part that is to be overwritten (Mask step 1) + or l ;; [1] Add up background and sprite information in one byte (Mask step 2) + ld (de), a ;; [2] Save modified background + sprite data information into memory + pop hl ;; [3] Recover HL (current byte sprite source) + + inc hl ;; [2] Next byte sprite source + inc de ;; [2] Next byte sprite colorized + djnz lineLoop ;; [3] Decrement B (Width) if B != 0 goto lineLoop + + dec c ;; [1] Decrement C (Height) + jr z, end ;; [2/3] If C == O goto end + + pop de ;; [3] Restore DE start line (DestMem + + ld a, d ;; [1] Start of next pixel line normally is 0x0800 bytes away. + add #0x08 ;; [2] so we add it to DE (just by adding 0x08 to D) + ld d, a ;; [1] + and #0x38 ;; [2] We check if we have crossed memory boundary (every 8 pixel lines).. + + jr nz, convertLoop ;; [2/3] .. by checking the 4 bits that identify present memory line. + ;; .... If 0, we have crossed boundaries + +dms_sprite_8bit_boundary_crossed: + ld a, e ;; [1] DE = DE + 0xC050h + add #0x50 ;; [2] -- Relocate DE pointer to the start of the next pixel line: + ld e, a ;; [1] -- DE is moved forward 3 memory banks plus 50 bytes (4000h * 3) + ld a, d ;; [1] -- which effectively is the same as moving it 1 bank backwards and then + adc #0xC0 ;; [2] -- 50 bytes forwards (which is what we want to move it to the next pixel line) + ld d, a ;; [1] -- Calculations are made with 8 bit maths as it is faster than other alternatives here + + jr convertLoop ;; [3] Jump to continue with next pixel line + +end: + pop de ;; [3] Empty stack by getting last element (DestMem) + ;; Return is included in bindings + diff --git a/cpctelera/src/sprites/colorReplace/M1/cpct_drawSpriteMaskedAlignedColorizeM1_asmbindings.s b/cpctelera/src/sprites/colorReplace/M1/cpct_drawSpriteMaskedAlignedColorizeM1_asmbindings.s new file mode 100644 index 000000000..db02086d7 --- /dev/null +++ b/cpctelera/src/sprites/colorReplace/M1/cpct_drawSpriteMaskedAlignedColorizeM1_asmbindings.s @@ -0,0 +1,36 @@ +;;-----------------------------LICENSE NOTICE------------------------------------ +;; This file is part of CPCtelera: An Amstrad CPC Game Engine +;; Copyright (C) 2017 Arnaud Bouche (Arnaud6128) +;; Copyright (C) 2017 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) +;; +;; This program is free software: you can redistribute it and/or modify +;; it under the terms of the GNU Lesser General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU Lesser General Public License for more details. +;; +;; You should have received a copy of the GNU Lesser General Public License +;; along with this program. If not, see <http://www.gnu.org/licenses/>. +;;------------------------------------------------------------------------------- +.module cpct_sprites + +.include "../../../macros/cpct_undocumentedOpcodes.s" + +;; +;; ASM bindings for <cpct_drawSpriteMaskedAlignedColorizeM1> +;; +cpct_drawSpriteMaskedAlignedColorizeM1_asm:: ;; Assembly entry point + + ;; GET Parameters from the stack + ld (dms_restore_ix + 2), ix ;; [6] Save IX to restore it before returning + pop hl ;; [3] HL = Return Address + +.include /cpct_drawSpriteMaskedAlignedColorizeM1.asm/ + +dms_restore_ix: + ld ix, #0000 ;; [4] Restore IX before returning + ret ;; [3] Return to caller \ No newline at end of file diff --git a/cpctelera/src/sprites/colorReplace/M1/cpct_drawSpriteMaskedAlignedColorizeM1_cbindings.s b/cpctelera/src/sprites/colorReplace/M1/cpct_drawSpriteMaskedAlignedColorizeM1_cbindings.s new file mode 100644 index 000000000..f0b0a2130 --- /dev/null +++ b/cpctelera/src/sprites/colorReplace/M1/cpct_drawSpriteMaskedAlignedColorizeM1_cbindings.s @@ -0,0 +1,53 @@ +;;-----------------------------LICENSE NOTICE------------------------------------ +;; This file is part of CPCtelera: An Amstrad CPC Game Engine +;; Copyright (C) 2017 Arnaud Bouche (Arnaud6128) +;; Copyright (C) 2017 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) +;; +;; This program is free software: you can redistribute it and/or modify +;; it under the terms of the GNU Lesser General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU Lesser General Public License for more details. +;; +;; You should have received a copy of the GNU Lesser General Public License +;; along with this program. If not, see <http://www.gnu.org/licenses/>. +;;------------------------------------------------------------------------------- +.module cpct_sprites + +.include "../../../macros/cpct_undocumentedOpcodes.s" + +;; +;; C bindings for <cpct_drawSpriteMaskedAlignedColorizeM1> +;; +;; 39 us, 16 bytes +;; +_cpct_drawSpriteMaskedAlignedColorizeM1:: + + ;; GET Parameters from the stack + ld (dms_restore_ix + 2), ix ;; [6] Save IX to restore it before returning + pop hl ;; [3] HL = Return Address + + exx ;; [1] Switch to Alternate registers + pop hl ;; [3] HL' = Source address (Sprite) + pop de ;; [3] DE' = Destination Memory + pop bc ;; [5] BC' = (B = Sprite Height, C = Width) + + exx ;; [1] Switch to Default registers + pop de ;; [3] DE = (D = newColor, E = oldColor) + + ex (sp), hl ;; [6] HL = Table Mask address + ;; ... and leave Return Address at (SP) as we don't need to restore + ;; ... stack status because callin convention is __z88dk_callee + + ex de, hl ;; [1] HL <-> DE + + +.include /cpct_drawSpriteMaskedAlignedColorizeM1.asm/ + +dms_restore_ix: + ld ix, #0000 ;; [4] Restore IX before returning + ret ;; [3] Return to caller \ No newline at end of file diff --git a/cpctelera/src/sprites/colorReplace/M1/cpct_drawSpriteMaskedColorizeM1.asm b/cpctelera/src/sprites/colorReplace/M1/cpct_drawSpriteMaskedColorizeM1.asm new file mode 100644 index 000000000..9188f2ef3 --- /dev/null +++ b/cpctelera/src/sprites/colorReplace/M1/cpct_drawSpriteMaskedColorizeM1.asm @@ -0,0 +1,246 @@ +;;-----------------------------LICENSE NOTICE------------------------------------ +;; This file is part of CPCtelera: An Amstrad CPC Game Engine +;; Copyright (C) 2017 Arnaud Bouche (Arnaud6128) +;; Copyright (C) 2017 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) +;; +;; This program is free software: you can redistribute it and/or modify +;; it under the terms of the GNU Lesser General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU Lesser General Public License for more details. +;; +;; You should have received a copy of the GNU Lesser General Public License +;; along with this program. If not, see <http://www.gnu.org/licenses/>. +;;------------------------------------------------------------------------------- +.module cpct_sprites + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; +;; Function: cpct_drawSpriteMaskedColorizeM1 +;; +;; Directly replace a color and draw a sprite Masked to video memory. +;; +;; C Definition: +;; void <cpct_drawSpriteMaskedColorizeM1> (void* *sprite*, void* *memory*, <u8> *width*, <u8> *height*, <u8> *oldColor*, <u8> *newColor*) __z88dk_callee; +;; +;; Input Parameters (8 bytes): +;; (2B HL') sprite - Source Sprite Pointer (array of pixel data) +;; (2B DE') memory - Destination video memory pointer +;; (1B C' ) height - Sprite Height in bytes (>0) +;; (1B B' ) width - Sprite Width in *bytes* (Beware, *not* in pixels!) +;; (1B L ) oldColor - Color to replace +;; (1B H ) newColor - New color +;; +;; Assembly call (Input parameters on registers): +;; > call cpct_drawSpriteMaskedColorizeM1_asm +;; +;; Parameter Restrictions: +;; * *sprite* must be an array containing sprite's pixels data in screen pixel format +;; along with mask data. Each mask byte will contain enabled bits as those that should +;; be picked from the background (transparent) and disabled bits for those that will +;; be printed from sprite colour data. Each mask data byte must precede its associated +;; colour data byte. +;; Sprite must be rectangular and all bytes in the array must be consecutive pixels, +;; starting from top-left corner and going left-to-right, top-to-bottom down to the +;; bottom-right corner. Total amount of bytes in pixel array should be +;; 2 x *width* x *height* (mask data doubles array size). +;; * *memory* could be any place in memory, inside or outside current video memory. It +;; will be equally treated as video memory (taking into account CPC's video memory +;; disposition). This lets you copy sprites to software or hardware backbuffers, and +;; not only video memory. +;; * *width* must be the width of the sprite *in bytes*. Always remember that the width must be +;; expressed in bytes and *not* in pixels. +;; The correspondence is mode 0 : 1 byte = 4 pixels +;; * *height* must be the height of the sprite in bytes, and must be greater than 0. +;; There is no practical upper limit to this value. Height of a sprite in +;; bytes and pixels is the same value, as bytes only group consecutive pixels in +;; the horizontal space. +;; * *oldColor* must be the index of color (0 to 3) to replace +;; * *newColor* must be the index of the new color (0 to 3) +;; +;; Known limitations: +;; * This function does not do any kind of boundary check or clipping. If you +;; try to draw sprites on the frontier of your video memory or screen buffer +;; if might potentially overwrite memory locations beyond boundaries. This +;; could cause your program to behave erratically, hang or crash. Always +;; take the necessary steps to guarantee that you are drawing inside screen +;; or buffer boundaries. +;; * As this function receives a byte-pointer to memory, it can only +;; draw byte-sized and byte-aligned sprites. This means that the box cannot +;; start on non-byte aligned pixels (like odd-pixels, for instance) and +;; their sizes must be a multiple of a byte (2 in mode 0, 4 in mode 1 and +;; 8 in mode 2). +;; * This function *will not work from ROM*, as it uses self-modifying code. +;; * This function requires the CPC firmware to be DISABLED. Otherwise, random crashes might happen due to side effects. +;; +;; Destroyed Register values: +;; AF, BC, DE, HL, BC', DE', HL', IX +;; +;; Required memory: +;; C-bindings - 142 bytes +;; ASM-bindings - 129 bytes +;; +;; Time Measures: +;; (start code) +;; Case | microSecs (us) | CPU Cycles +;; ---------------------------------------------------------------- +;; | 29 + (36 + 93W)H | 116 + (144 + 372W)H +;; ---------------------------------------------------------------- +;; W=2,H=16 | 3581 | 14324 +;; W=4,H=32 | 13085 | 52340 +;; ---------------------------------------------------------------- +;; Asm saving | -16 | -64 +;; ---------------------------------------------------------------- +;; (end code) +;; W = *width* in bytes, H = *height* in bytes +;; +;; Credits: +;; Original routine optimized by @Docent and discussed in CPCWiki : +;; http://www.cpcwiki.eu/forum/programming/cpctelera-colorize-sprite/ +;; +;; Thanks to all of them for their help and support. +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +.globl dc_mode1_ct + +;; Macro to convert color to pixel Mode1 : Axxx Axxx +.macro convertPixel ;; From cpct_px2byteM1 + ld bc, #dc_mode1_ct ;; [3] BC points to conversion table (dc_mode1_ct) + + ;; Compute BC += A + add c ;; [1] | C += A + ld c, a ;; [1] | + sub a ;; [1] A = 0 (preserving Carry Flag) + adc b ;; [1] | B += Carry + ld b, a ;; [1] | + + ;; A = *(BC + A) + ld a, (bc) ;; [2] A = Value stored at the table pointed by BC +.endm + + ;; Convert newColor to pixel format (E) + ld a, h ;; [1] A = H new color index + convertPixel ;; [10] | Convert into A + ld e, a ;; [1] | E = A new color : Axxx Axxx + + ;; Convert oldColor to pixel format (D) + ld a, l ;; [1] A = L old color index + convertPixel ;; [10] | Convert into A + ld d, a ;; [1] | D = A old color : Axxx Axxx + + ld c, #0x88 ;; [2] C = First Mask to get pixel A : Axxx Axxx + exx ;; [1] Switch to Alternate registers + + ld__ixl_c ;; [1] IXL = C (Width) + ld c, b ;; [1] C = B (Height) + +convertLoop: + ld (startLine), de ;; [6] Store DE start line (DestMem) + ld__b_ixl ;; [2] B = IXL (Sprite Width) + +lineLoop: + inc hl ;; [2] Next byte sprite Color source + ld a, (hl) ;; [2] A = (HL) current Byte of sprite Color + dec hl ;; [2] Previous byte sprite Mask source + + exx ;; [1] Switch to Default registers + + ld l, a ;; [1] L = A current Byte of sprite : ABCD ABCD + + and c ;; [2] A |= C (C = 0x88) : Axxx Axxx + + cp d ;; [1] Test if pixel (A) is the old colour to be replaced (D) + jr nz, readPixelA ;; [2/3] If not equal go to next pixel + ld a, e ;; [1] else A = new colour to set (E) + +readPixelA: + ld h, a ;; [1] H = A (current colorized sprite) : Axxx Axxx + + sla l ;; [2] L (current byte of sprite) << 1 : ABCD ABCD -> BCDx BCDx + ld a, l ;; [1] A = L : BCDx BCDx + and c ;; [2] A |= Mask (0x88) : Bxxx Bxxx + + cp d ;; [1] Test if pixel (A) is the old colour to be replaced (D) + jr nz, readPixelB ;; [2/3] If not equal go to next pixel + ld a, e ;; [1] else A = new colour to set (E) + +readPixelB: + rrca ;; [1] A = Axxx Axxx >> 1 : xBxx xBxx + or h ;; [1] A |= H (color byte) : Axxx Axxx + ld h, a ;; [1] H = A : ABxx ABxx + + sla l ;; [2] L ( BCDx BCDx) << 1 : CDxx CDxx + ld a, l ;; [1] A = L : CDxx CDxx + and c ;; [1] A |= C (C = 0x88) : Cxxx Cxxx + + cp d ;; [1] Test if pixel (A) is the old colour to be replaced (D) + jr nz, readPixelC ;; [2/3] If not equal go to next pixel + ld a, e ;; [1] else A = new colour to set (E) + +readPixelC: + rrca ;; [1] A = Axxx Axxx >> 1 : xBxx xBxx + rrca ;; [1] A = xxCx xxCx << 1 : xxCx xxCx + or h ;; [1] A |= H (ABxx ABxx) : ABCx ABCx + ld h, a ;; [1] H = A : ABCx ABCx + + sla l ;; [2] L (BCDx BCDx) << 1 : Dxxx Dxxx + ld a, l ;; [1] A = L : Dxxx Dxxx + and c ;; [1] A |= C (C = 0x88) : Dxxx Dxxx + + cp d ;; [1] Test if pixel (A) is the old colour to be replaced (D) + jr nz, readPixelD ;; [2/3] If not equal go to next pixel + ld a, e ;; [1] else A = new colour to set (E) + +readPixelD: + rrca ;; [1] A = Axxx Axxx >> 1 : xBxx xBxx + rrca ;; [1] A = xBxx xBxx >> 1 : xxCx xxCx + rrca ;; [1] A = xxCx xxxx >> 1 : xxxD xxxD + or h ;; [1] A |= H (ABCx ABCx) : ABCD ABCD + + exx ;; [1] Switch to Alternate registers + +drawByte: + ld (sprite_color), a ;; [4] sprite_color = A (Sprite Byte) + + ld a, (de) ;; [2] Get next background byte into A + and (hl) ;; [2] Erase background part that is to be overwritten (Mask step 1) + inc hl ;; [3] HL += 1 => Point HL to Sprite Colour information +sprite_color = .+1 ;; Placeholder for the Sprite Color computed + or #00 ;; [2] Add up background and sprite information in one byte (Mask step 2) + ld (de), a ;; [2] Save modified background + sprite data information into memory + + inc hl ;; [2] Next byte sprite source + inc de ;; [2] Next byte Dest Memory + djnz lineLoop ;; [3] Decrement B (Width) if B != 0 goto lineLoop + + dec c ;; [1] Decrement C (Height) + jr z, end ;; [2/3] If C == O goto end + +startLine = .+1 ;; Placeholder for the Start line adress + ld de, #0000 ;; [3] DE = Start Line + + ld a, d ;; [1] Start of next pixel line normally is 0x0800 bytes away. + add #0x08 ;; [2] so we add it to DE (just by adding 0x08 to D) + ld d, a ;; [1] + and #0x38 ;; [2] We check if we have crossed memory boundary (every 8 pixel lines).. + + jr nz, convertLoop ;; [2/3] .. by checking the 4 bits that identify present memory line. + ;; .... If 0, we have crossed boundaries + +dms_sprite_8bit_boundary_crossed: + ld a, e ;; [1] DE = DE + 0xC050h + add #0x50 ;; [2] -- Relocate DE pointer to the start of the next pixel line: + ld e, a ;; [1] -- DE is moved forward 3 memory banks plus 50 bytes (4000h * 3) + ld a, d ;; [1] -- which effectively is the same as moving it 1 bank backwards and then + adc #0xC0 ;; [2] -- 50 bytes forwards (which is what we want to move it to the next pixel line) + ld d, a ;; [1] -- Calculations are made with 8 bit maths as it is faster than other alternatives here + + jr convertLoop ;; [3] Jump to continue with next pixel line + +end: + ;; Return is included in bindings + diff --git a/cpctelera/src/sprites/colorReplace/M1/cpct_drawSpriteMaskedColorizeM1_asmbindings.s b/cpctelera/src/sprites/colorReplace/M1/cpct_drawSpriteMaskedColorizeM1_asmbindings.s new file mode 100644 index 000000000..b2ed10933 --- /dev/null +++ b/cpctelera/src/sprites/colorReplace/M1/cpct_drawSpriteMaskedColorizeM1_asmbindings.s @@ -0,0 +1,36 @@ +;;-----------------------------LICENSE NOTICE------------------------------------ +;; This file is part of CPCtelera: An Amstrad CPC Game Engine +;; Copyright (C) 2017 Arnaud Bouche (Arnaud6128) +;; Copyright (C) 2017 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) +;; +;; This program is free software: you can redistribute it and/or modify +;; it under the terms of the GNU Lesser General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU Lesser General Public License for more details. +;; +;; You should have received a copy of the GNU Lesser General Public License +;; along with this program. If not, see <http://www.gnu.org/licenses/>. +;;------------------------------------------------------------------------------- +.module cpct_sprites + +.include "../../../macros/cpct_undocumentedOpcodes.s" + +;; +;; ASM bindings for <cpct_drawSpriteMaskedColorizeM1> +;; +cpct_drawSpriteMaskedColorizeM1_asm:: ;; Assembly entry point + + ;; GET Parameters from the stack + ld (dms_restore_ix + 2), ix ;; [6] Save IX to restore it before returning + pop hl ;; [3] HL = Return Address + +.include /cpct_drawSpriteMaskedColorizeM1.asm/ + +dms_restore_ix: + ld ix, #0000 ;; [4] Restore IX before returning + ret ;; [3] Return to caller \ No newline at end of file diff --git a/cpctelera/src/sprites/colorReplace/M1/cpct_drawSpriteMaskedColorizeM1_cbindings.s b/cpctelera/src/sprites/colorReplace/M1/cpct_drawSpriteMaskedColorizeM1_cbindings.s new file mode 100644 index 000000000..aa21c471c --- /dev/null +++ b/cpctelera/src/sprites/colorReplace/M1/cpct_drawSpriteMaskedColorizeM1_cbindings.s @@ -0,0 +1,48 @@ +;;-----------------------------LICENSE NOTICE------------------------------------ +;; This file is part of CPCtelera: An Amstrad CPC Game Engine +;; Copyright (C) 2017 Arnaud Bouche (Arnaud6128) +;; Copyright (C) 2017 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) +;; +;; This program is free software: you can redistribute it and/or modify +;; it under the terms of the GNU Lesser General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU Lesser General Public License for more details. +;; +;; You should have received a copy of the GNU Lesser General Public License +;; along with this program. If not, see <http://www.gnu.org/licenses/>. +;;------------------------------------------------------------------------------- +.module cpct_sprites + +.include "../../../macros/cpct_undocumentedOpcodes.s" + +;; +;; C bindings for <cpct_drawSpriteMaskedColorizeM1> +;; +;; 33 us, 13 bytes +;; +_cpct_drawSpriteMaskedColorizeM1:: + + ;; GET Parameters from the stack + ld (dms_restore_ix + 2), ix ;; [6] Save IX to restore it before returning + pop hl ;; [3] HL = Return Address + + exx + pop hl ;; [3] HL' = Source address (Sprite) + pop de ;; [3] DE' = Destination Memory + pop bc ;; [5] BC' = (B = Sprite Height, C = Width) + exx + + ex (sp), hl ;; [6] HL = (H = newColor, L = oldColor) + ;; ... and leave Return Address at (SP) as we don't need to restore + ;; ... stack status because callin convention is __z88dk_callee + +.include /cpct_drawSpriteMaskedColorizeM1.asm/ + +dms_restore_ix: + ld ix, #0000 ;; [4] Restore IX before returning + ret ;; [3] Return to caller \ No newline at end of file diff --git a/cpctelera/src/sprites/colorReplace/M1/cpct_spriteColorizeM1.asm b/cpctelera/src/sprites/colorReplace/M1/cpct_spriteColorizeM1.asm new file mode 100644 index 000000000..be64dd10b --- /dev/null +++ b/cpctelera/src/sprites/colorReplace/M1/cpct_spriteColorizeM1.asm @@ -0,0 +1,194 @@ +;;-----------------------------LICENSE NOTICE------------------------------------ +;; This file is part of CPCtelera: An Amstrad CPC Game Engine +;; Copyright (C) 2017 Arnaud Bouche (Arnaud6128) +;; Copyright (C) 2017 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) +;; +;; This program is free software: you can redistribute it and/or modify +;; it under the terms of the GNU Lesser General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU Lesser General Public License for more details. +;; +;; You should have received a copy of the GNU Lesser General Public License +;; along with this program. If not, see <http://www.gnu.org/licenses/>. +;;------------------------------------------------------------------------------- +.module cpct_sprites + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; +;; Function: cpct_spriteColorizeM1 +;; +;; Replace a color in a sprite and copy to another or the same sprite. +;; +;; C Definition: +;; void <cpct_spriteColorizeM1> (void* *sprite*, void* *spriteColor*, <u8> *width*, <u8> *height*, <u8> *oldColor*, <u8> *newColor*) __z88dk_callee; +;; +;; Input Parameters (6 bytes): +;; (2B HL') sprite - Source Sprite Pointer (array of pixel data) +;; (2B DE') spriteColor - Destination Sprite Pointer (can be also the Source Sprite) (array of pixel data) +;; (1B C' ) height - Sprite Height in bytes (>0) +;; (1B B' ) width - Sprite Width in *bytes* (Beware, *not* in pixels!) +;; (1B L ) oldColor - Color to replace +;; (1B H ) newColor - New color +;; +;; Assembly call (Input parameters on registers): +;; > call cpct_spriteColorizeM1_asm +;; +;; Parameter Restrictions: +;; * *sprite* must be an array containing sprite's pixels data in screen pixel format. +;; Sprite must be rectangular and all bytes in the array must be consecutive pixels, +;; starting from top-left corner and going left-to-right, top-to-bottom down to the +;; bottom-right corner. Total amount of bytes in pixel array should be *width* x *height*. +;; * *spriteColor* must be an array containing the new sprite's pixels data with the new color. +;; * *width* must be the width of the sprite *in bytes*. Always remember that the width must be +;; expressed in bytes and *not* in pixels. +;; The correspondence is mode 1 : 1 byte = 4 pixels +;; * *height* must be the height of the sprite in bytes, and must be greater than 0. +;; There is no practical upper limit to this value. Height of a sprite in +;; bytes and pixels is the same value, as bytes only group consecutive pixels in +;; the horizontal space. +;; * *oldColor* must be the index of color (0 to 3) to replace +;; * *newColor* must be the index of the new color (0 to 3) +;; +;; Known limitations: +;; * This function *will not work from ROM*, as it uses self-modifying code. +;; * This function requires the CPC firmware to be DISABLED. Otherwise, random crashes might happen due to side effects. +;; +;; Destroyed Register values: +;; AF, BC, DE, HL, BC', DE', HL', IX +;; +;; Required memory: +;; C-bindings - 73 bytes +;; ASM-bindings - 60 bytes +;; +;; Time Measures: +;; (start code) +;; Case | microSecs (us) | CPU Cycles +;; ---------------------------------------------------------------- +;; | 29 + (6 + 61W)H | 116 + (24 + 244W)H +;; ---------------------------------------------------------------- +;; W=2,H=16 | 2077 | 8308 +;; W=4,H=32 | 8029 | 32116 +;; ---------------------------------------------------------------- +;; Asm saving | -16 | -64 +;; ---------------------------------------------------------------- +;; (end code) +;; W = *width* in bytes, H = *height* in bytes +;; +;; Credits: +;; Original routine optimized by @Docent and discussed in CPCWiki : +;; http://www.cpcwiki.eu/forum/programming/cpctelera-colorize-sprite/ +;; +;; Thanks to all of them for their help and support. +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +.globl dc_mode1_ct + +;; Macro to convert color to pixel Mode1 : Axxx Axxx +.macro convertPixel ;; From cpct_px2byteM1 + ld bc, #dc_mode1_ct ;; [3] BC points to conversion table (dc_mode1_ct) + + ;; Compute HL += A + add c ;; [1] | C += A + ld c, a ;; [1] | + sub a ;; [1] A = 0 (preserving Carry Flag) + adc b ;; [1] | L += Carry + ld b, a ;; [1] | + + ;; A = *(BC + A) + ld a, (bc) ;; [2] A = Value stored at the table pointed by BC +.endm + + ;; Convert newColor to pixel format (E) + ld a, h ;; [1] A = H new color index + convertPixel ;; [10] | Convert into A + ld e, a ;; [1] | E = A new color : Axxx Axxx + + ;; Convert oldColor to pixel format (D) + ld a, l ;; [1] A = L old color index + convertPixel ;; [10] | Convert into A + ld d, a ;; [1] | D = A old color : Axxx Axxx + + ld c, #0x88 ;; [2] C = First Mask to get pixel A : Axxx Axxx + + exx ;; [1] Switch to Alternate registers + + ld__ixl_c ;; [1] IXL = C (Width) + ld c, b ;; [1] C = B (Height) + +convertLoop: + ld__b_ixl ;; [2] B = IXL (Sprite Width) + +lineLoop: + ld a, (hl) ;; [2] A = (HL) current Byte of sprite + exx ;; [1] Switch to Default registers + + ld l, a ;; [1] L = A current Byte of sprite : ABCD ABCD + and c ;; [2] A |= C (C = 0x88) : Axxx Axxx + + cp d ;; [1] Test if pixel (A) is the old colour to be replaced (D) + jr nz, readPixelA ;; [2/3] If not equal go to next pixel + ld a, e ;; [1] else A = new colour to set (E) + +readPixelA: + ld h, a ;; [1] H = A (current colorized sprite) : Axxx Axxx + + sla l ;; [2] L (current byte of sprite) << 1 : ABCD ABCD -> BCDx BCDx + ld a, l ;; [1] A = L : BCDx BCDx + and c ;; [2] A |= Mask (0x88) : Bxxx Bxxx + + cp d ;; [1] Test if pixel (A) is the old colour to be replaced (D) + jr nz, readPixelB ;; [2/3] If not equal go to next pixel + ld a, e ;; [1] else A = new colour to set (E) + +readPixelB: + rrca ;; [1] A = Axxx Axxx >> 1 : xBxx xBxx + or h ;; [1] A |= H (color byte) : Axxx Axxx + ld h, a ;; [1] H = A : ABxx ABxx + + sla l ;; [2] L ( BCDx BCDx) << 1 : CDxx CDxx + ld a, l ;; [1] A = L : CDxx CDxx + and c ;; [1] A |= C (C = 0x88) : Cxxx Cxxx + + cp d ;; [1] Test if pixel (A) is the old colour to be replaced (D) + jr nz, readPixelC ;; [2/3] If not equal go to next pixel + ld a, e ;; [1] else A = new colour to set (E) + +readPixelC: + rrca ;; [1] A = Axxx Axxx >> 1 : xBxx xBxx + rrca ;; [1] A = xxCx xxCx << 1 : xxCx xxCx + or h ;; [1] A |= H (ABxx ABxx) : ABCx ABCx + ld h, a ;; [1] H = A : ABCx ABCx + + sla l ;; [2] L (BCDx BCDx) << 1 : Dxxx Dxxx + ld a, l ;; [1] A = L : Dxxx Dxxx + and c ;; [1] A |= C (C = 0x88) : Dxxx Dxxx + + cp d ;; [1] Test if pixel (A) is the old colour to be replaced (D) + jr nz, readPixelD ;; [2/3] If not equal go to next pixel + ld a, e ;; [1] else A = new colour to set (E) + +readPixelD: + rrca ;; [1] A = Axxx Axxx >> 1 : xBxx xBxx + rrca ;; [1] A = xBxx xBxx >> 1 : xxCx xxCx + rrca ;; [1] A = xxCx xxxx >> 1 : xxxD xxxD + or h ;; [1] A |= H (ABCx ABCx) : ABCD ABCD + +setByte: + exx ;; [1] Switch to Alternate registers + + ld (de), a ;; [2] Update current sprite byte with pixels + inc hl ;; [2] Next byte sprite source + inc de ;; [2] Next byte sprite colorized + djnz lineLoop ;; [3] Decrement B (Width) if != 0 goto lineLoop + +nextLine: + dec c ;; [1] Decrement C (Height) + jr nz, convertLoop ;; [2/3] If != O goto convertLoop + +end: + ;; Return is included in bindings + diff --git a/cpctelera/src/sprites/colorReplace/M1/cpct_spriteColorizeM1_asmbindings.s b/cpctelera/src/sprites/colorReplace/M1/cpct_spriteColorizeM1_asmbindings.s new file mode 100644 index 000000000..4deb6e35b --- /dev/null +++ b/cpctelera/src/sprites/colorReplace/M1/cpct_spriteColorizeM1_asmbindings.s @@ -0,0 +1,35 @@ +;;-----------------------------LICENSE NOTICE------------------------------------ +;; This file is part of CPCtelera: An Amstrad CPC Game Engine +;; Copyright (C) 2017 Arnaud Bouche (Arnaud6128) +;; Copyright (C) 2017 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) +;; +;; This program is free software: you can redistribute it and/or modify +;; it under the terms of the GNU Lesser General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU Lesser General Public License for more details. +;; +;; You should have received a copy of the GNU Lesser General Public License +;; along with this program. If not, see <http://www.gnu.org/licenses/>. +;;------------------------------------------------------------------------------- +.module cpct_sprites + +.include "../../../macros/cpct_undocumentedOpcodes.s" + +;; +;; ASM bindings for <cpct_spriteColorizeM1> +;; +cpct_spriteColorizeM1_asm:: ;; Assembly entry point + + ;; GET Parameters from the stack + ld (dms_restore_ix + 2), ix ;; [6] Save IX to restore it before returning + +.include /cpct_spriteColorizeM1.asm/ + +dms_restore_ix: + ld ix, #0000 ;; [4] Restore IX before returning + ret ;; [3] Return to caller \ No newline at end of file diff --git a/cpctelera/src/sprites/colorReplace/M1/cpct_spriteColorizeM1_cbindings.s b/cpctelera/src/sprites/colorReplace/M1/cpct_spriteColorizeM1_cbindings.s new file mode 100644 index 000000000..8bca05567 --- /dev/null +++ b/cpctelera/src/sprites/colorReplace/M1/cpct_spriteColorizeM1_cbindings.s @@ -0,0 +1,48 @@ +;;-----------------------------LICENSE NOTICE------------------------------------ +;; This file is part of CPCtelera: An Amstrad CPC Game Engine +;; Copyright (C) 2017 Arnaud Bouche (Arnaud6128) +;; Copyright (C) 2017 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) +;; +;; This program is free software: you can redistribute it and/or modify +;; it under the terms of the GNU Lesser General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU Lesser General Public License for more details. +;; +;; You should have received a copy of the GNU Lesser General Public License +;; along with this program. If not, see <http://www.gnu.org/licenses/>. +;;------------------------------------------------------------------------------- +.module cpct_sprites + +.include "../../../macros/cpct_undocumentedOpcodes.s" + +;; +;; C bindings for <cpct_spriteColorizeM1> +;; +;; 33 us, 13 bytes +;; +_cpct_spriteColorizeM1:: + + ;; GET Parameters from the stack + ld (dms_restore_ix + 2), ix ;; [6] Save IX to restore it before returning + pop hl ;; [3] HL = Return Address + + exx + pop hl ;; [3] HL' = Source address (Sprite) + pop de ;; [3] DE' = Destination Sprite color + pop bc ;; [5] BC' = (B = Sprite Height, C = Width) + exx + + ex (sp), hl ;; [6] HL = (H = newColor, L = oldColor) + ;; ... and leave Return Address at (SP) as we don't need to restore + ;; ... stack status because callin convention is __z88dk_callee + +.include /cpct_spriteColorizeM1.asm/ + +dms_restore_ix: + ld ix, #0000 ;; [4] Restore IX before returning + ret ;; [3] Return to caller \ No newline at end of file diff --git a/cpctelera/src/sprites/colorReplace/M1/cpct_spriteMaskedColorizeM1.asm b/cpctelera/src/sprites/colorReplace/M1/cpct_spriteMaskedColorizeM1.asm new file mode 100644 index 000000000..c135f3fa7 --- /dev/null +++ b/cpctelera/src/sprites/colorReplace/M1/cpct_spriteMaskedColorizeM1.asm @@ -0,0 +1,205 @@ +;;-----------------------------LICENSE NOTICE------------------------------------ +;; This file is part of CPCtelera: An Amstrad CPC Game Engine +;; Copyright (C) 2017 Arnaud Bouche (Arnaud6128) +;; Copyright (C) 2017 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) +;; +;; This program is free software: you can redistribute it and/or modify +;; it under the terms of the GNU Lesser General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU Lesser General Public License for more details. +;; +;; You should have received a copy of the GNU Lesser General Public License +;; along with this program. If not, see <http://www.gnu.org/licenses/>. +;;------------------------------------------------------------------------------- +.module cpct_sprites +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; +;; Function: cpct_spriteMaskedColorizeM1 +;; +;; Replace a color in a Masked sprite and copy to another or the same sprite. +;; +;; C Definition: +;; void <cpct_spriteMaskedColorizeM1> (void* *sprite*, void* *spriteColor*, <u8> *width*, <u8> *height*, <u8> *oldColor*, <u8> *newColor*) __z88dk_callee; +;; +;; Input Parameters (6 bytes): +;; (2B HL') sprite - Source Sprite Pointer (array of pixel data) +;; (2B DE') spriteColor - Destination Sprite Pointer (can be also the Source Sprite) (array of pixel data) +;; (1B C') height - Sprite Height in bytes (>0) +;; (1B B') width - Sprite Width in *bytes* (Beware, *not* in pixels!) +;; (1B L) oldColor - Color to replace +;; (1B H) newColor - New color +;; +;; Assembly call (Input parameters on registers): +;; > call cpct_spriteMaskedColorizeM1_asm +;; +;; Parameter Restrictions: +;; * *sprite* must be an array containing sprite's pixels data in screen pixel format +;; along with mask data. Each mask byte will contain enabled bits as those that should +;; be picked from the background (transparent) and disabled bits for those that will +;; be printed from sprite colour data. Each mask data byte must precede its associated +;; colour data byte. +;; Sprite must be rectangular and all bytes in the array must be consecutive pixels, +;; starting from top-left corner and going left-to-right, top-to-bottom down to the +;; bottom-right corner. Total amount of bytes in pixel array should be +;; 2 x *width* x *height* (mask data doubles array size). +;; * *spriteColor* must be an array containing the new sprite's pixels data with the new color. +;; Total amount of bytes in pixel array should be 2 x *width* x *height* (mask data doubles array size). +;; * *width* must be the width of the sprite *in bytes*. Always remember that the width must be +;; expressed in bytes and *not* in pixels. +;; The correspondence is mode 1 : 1 byte = 4 pixels +;; * *height* must be the height of the sprite in bytes, and must be greater than 0. +;; There is no practical upper limit to this value. Height of a sprite in +;; bytes and pixels is the same value, as bytes only group consecutive pixels in +;; the horizontal space. +;; * *oldColor* must be the index of color (0 to 3) to replace +;; * *newColor* must be the index of the new color (0 to 3) +;; +;; Known limitations: +;; * This function *will not work from ROM*, as it uses self-modifying code. +;; * This function requires the CPC firmware to be DISABLED. Otherwise, random crashes might happen due to side effects. +;; +;; Destroyed Register values: +;; AF, BC, DE, HL, BC', DE', HL', IX +;; +;; Required memory: +;; C-bindings - 110 bytes +;; ASM-bindings - 97 bytes +;; +;; Time Measures: +;; (start code) +;; Case | microSecs (us) | CPU Cycles +;; ---------------------------------------------------------------- +;; | 29 + (6 + 71W)H | 116 + (24 + 284W)H +;; ---------------------------------------------------------------- +;; W=2,H=16 | 2397 | 9588 +;; W=4,H=32 | 9309 | 37236 +;; ---------------------------------------------------------------- +;; Asm saving | -16 | -64 +;; ---------------------------------------------------------------- +;; (end code) +;; W = *width* in bytes, H = *height* in bytes +;; +;; Credits: +;; Original routine optimized by @Docent and discussed in CPCWiki : +;; http://www.cpcwiki.eu/forum/programming/cpctelera-colorize-sprite/ +;; +;; Thanks to all of them for their help and support. +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +.globl dc_mode1_ct + +;; Macro to convert color to pixel Mode1 : Axxx Axxx +.macro convertPixel ;; From cpct_px2byteM1 + ld bc, #dc_mode1_ct ;; [3] HL points to conversion table (dc_mode1_ct) + + ;; Compute HL += A + add c ;; [1] | L += A + ld c, a ;; [1] | + sub a ;; [1] A = 0 (preserving Carry Flag) + adc b ;; [1] | H += Carry + ld b, a ;; [1] | + + ;; A = *(HL + A) + ld a, (bc) ;; [2] A = Value stored at the table pointed by HL +.endm + + ;; Convert newColor to pixel format (E) + ld a, h ;; [1] A = H new color index + convertPixel ;; [10] | Convert into A + ld e, a ;; [1] | E = A new color : Axxx Axxx + + ;; Convert oldColor to pixel format (D) + ld a, l ;; [1] A = L old color index + convertPixel ;; [10] | Convert into A + ld d, a ;; [1] | D = A old color : Axxx Axxx + + ld c, #0x88 ;; [2] C = First Mask to get pixel A : Axxx Axxx + + exx ;; [1] Switch to Alternate registers + + ld__ixl_c ;; [1] IXL = C (Width) + ld c, b ;; [1] C = B (Height) + +convertLoop: + ld__b_ixl ;; [2] B = IXL (Sprite Width) + +lineLoop: + ld a, (hl) ;; [2] A = (HL) current Byte of sprite Mask + ld (de), a ;; [2] (DE) = A Copy of sprite Mask + inc hl ;; [2] Next byte sprite Color source + inc de ;; [2] Next byte sprite Color destination + ld a, (hl) ;; [2] A = (HL) current Byte of sprite Color + + exx ;; [1] Switch to Default registers + + ld l, a ;; [1] L = A current Byte of sprite : ABCD ABCD + + and c ;; [2] A |= C (C = 0x88) : Axxx Axxx + + cp d ;; [1] Test if pixel (A) is the old colour to be replaced (D) + jr nz, readPixelA ;; [2/3] If not equal go to next pixel + ld a, e ;; [1] else A = new colour to set (E) + +readPixelA: + ld h, a ;; [1] H = A (current colorized sprite) : Axxx Axxx + + sla l ;; [2] L (current byte of sprite) << 1 : ABCD ABCD -> BCDx BCDx + ld a, l ;; [1] A = L : BCDx BCDx + and c ;; [2] A |= Mask (0x88) : Bxxx Bxxx + + cp d ;; [1] Test if pixel (A) is the old colour to be replaced (D) + jr nz, readPixelB ;; [2/3] If not equal go to next pixel + ld a, e ;; [1] else A = new colour to set (E) + +readPixelB: + rrca ;; [1] A = Axxx Axxx >> 1 : xBxx xBxx + or h ;; [1] A |= H (color byte) : Axxx Axxx + ld h, a ;; [1] H = A : ABxx ABxx + + sla l ;; [2] L ( BCDx BCDx) << 1 : CDxx CDxx + ld a, l ;; [1] A = L : CDxx CDxx + and c ;; [1] A |= C (C = 0x88) : Cxxx Cxxx + + cp d ;; [1] Test if pixel (A) is the old colour to be replaced (D) + jr nz, readPixelC ;; [2/3] If not equal go to next pixel + ld a, e ;; [1] else A = new colour to set (E) + +readPixelC: + rrca ;; [1] A = Axxx Axxx >> 1 : xBxx xBxx + rrca ;; [1] A = xxCx xxCx << 1 : xxCx xxCx + or h ;; [1] A |= H (ABxx ABxx) : ABCx ABCx + ld h, a ;; [1] H = A : ABCx ABCx + + sla l ;; [2] L (BCDx BCDx) << 1 : Dxxx Dxxx + ld a, l ;; [1] A = L : Dxxx Dxxx + and c ;; [1] A |= C (C = 0x88) : Dxxx Dxxx + + cp d ;; [1] Test if pixel (A) is the old colour to be replaced (D) + jr nz, readPixelD ;; [2/3] If not equal go to next pixel + ld a, e ;; [1] else A = new colour to set (E) + +readPixelD: + rrca ;; [1] A = Axxx Axxx >> 1 : xBxx xBxx + rrca ;; [1] A = xBxx xBxx >> 1 : xxCx xxCx + rrca ;; [1] A = xxCx xxxx >> 1 : xxxD xxxD + or h ;; [1] A |= H (ABCx ABCx) : ABCD ABCD + +setByte: + exx ;; [1] Switch to Alternate registers + + ld (de), a ;; [2] Update current sprite byte with pixels + inc hl ;; [2] Next byte sprite source + inc de ;; [2] Next byte sprite colorized + djnz lineLoop ;; [3] Decrement B (Width) if != 0 goto lineLoop + +nextLine: + dec c ;; [1] Decrement C (Height) + jr nz, convertLoop ;; [2/3] If != O goto convertLoop + +end: + ;; Return is included in bindings \ No newline at end of file diff --git a/cpctelera/src/sprites/colorReplace/M1/cpct_spriteMaskedColorizeM1_asmbindings.s b/cpctelera/src/sprites/colorReplace/M1/cpct_spriteMaskedColorizeM1_asmbindings.s new file mode 100644 index 000000000..cc7d49e23 --- /dev/null +++ b/cpctelera/src/sprites/colorReplace/M1/cpct_spriteMaskedColorizeM1_asmbindings.s @@ -0,0 +1,36 @@ +;;-----------------------------LICENSE NOTICE------------------------------------ +;; This file is part of CPCtelera: An Amstrad CPC Game Engine +;; Copyright (C) 2017 Arnaud Bouche (Arnaud6128) +;; Copyright (C) 2017 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) +;; +;; This program is free software: you can redistribute it and/or modify +;; it under the terms of the GNU Lesser General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU Lesser General Public License for more details. +;; +;; You should have received a copy of the GNU Lesser General Public License +;; along with this program. If not, see <http://www.gnu.org/licenses/>. +;;------------------------------------------------------------------------------- +.module cpct_sprites + +.include "../../../macros/cpct_undocumentedOpcodes.s" + +;; +;; ASM bindings for <cpct_spriteMaskedColorizeM1> +;; +cpct_spriteMaskedColorizeM1_asm:: ;; Assembly entry point + + ;; GET Parameters from the stack + ld (dms_restore_ix + 2), ix ;; [6] Save IX to restore it before returning + pop hl ;; [3] HL = Return Address + +.include /cpct_spriteMaskedColorizeM1.asm/ + +dms_restore_ix: + ld ix, #0000 ;; [4] Restore IX before returning + ret ;; [3] Return to caller \ No newline at end of file diff --git a/cpctelera/src/sprites/colorReplace/M1/cpct_spriteMaskedColorizeM1_cbindings.s b/cpctelera/src/sprites/colorReplace/M1/cpct_spriteMaskedColorizeM1_cbindings.s new file mode 100644 index 000000000..3e4784f8a --- /dev/null +++ b/cpctelera/src/sprites/colorReplace/M1/cpct_spriteMaskedColorizeM1_cbindings.s @@ -0,0 +1,48 @@ +;;-----------------------------LICENSE NOTICE------------------------------------ +;; This file is part of CPCtelera: An Amstrad CPC Game Engine +;; Copyright (C) 2017 Arnaud Bouche (Arnaud6128) +;; Copyright (C) 2017 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) +;; +;; This program is free software: you can redistribute it and/or modify +;; it under the terms of the GNU Lesser General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU Lesser General Public License for more details. +;; +;; You should have received a copy of the GNU Lesser General Public License +;; along with this program. If not, see <http://www.gnu.org/licenses/>. +;;------------------------------------------------------------------------------- +.module cpct_sprites + +.include "../../../macros/cpct_undocumentedOpcodes.s" + +;; +;; C bindings for <cpct_spriteMaskedColorizeM1> +;; +;; 33 us, 13 bytes +;; +_cpct_spriteMaskedColorizeM1:: + + ;; GET Parameters from the stack + ld (dms_restore_ix + 2), ix ;; [6] Save IX to restore it before returning + pop hl ;; [3] HL = Return Address + + exx + pop hl ;; [3] HL' = Source address (Sprite) + pop de ;; [3] DE' = Destination Sprite color + pop bc ;; [5] BC' = (B = Sprite Height, C = Width) + exx + + ex (sp), hl ;; [6] HL = (H = newColor, L = oldColor) + ;; ... and leave Return Address at (SP) as we don't need to restore + ;; ... stack status because callin convention is __z88dk_callee + +.include /cpct_spriteMaskedColorizeM1.asm/ + +dms_restore_ix: + ld ix, #0000 ;; [4] Restore IX before returning + ret ;; [3] Return to caller \ No newline at end of file From cc8a04918ed53103a2d09972a71645e661a3a8e1 Mon Sep 17 00:00:00 2001 From: Arnaud <arnaud_bouche@hotmail.com> Date: Fri, 19 Jan 2018 21:03:36 +0100 Subject: [PATCH 02/31] Add sprite color replace functions M0 and M1 --- .../M0/cpct_drawSpriteColorizeM0.asm | 203 +++++++++++++++ .../cpct_drawSpriteColorizeM0_asmbindings.s | 36 +++ .../M0/cpct_drawSpriteColorizeM0_cbindings.s | 48 ++++ ...cpct_drawSpriteMaskedAlignedColorizeM0.asm | 215 +++++++++++++++ ...priteMaskedAlignedColorizeM0_asmbindings.s | 36 +++ ...wSpriteMaskedAlignedColorizeM0_cbindings.s | 52 ++++ .../M0/cpct_drawSpriteMaskedColorizeM0.asm | 216 +++++++++++++++ ...t_drawSpriteMaskedColorizeM0_asmbindings.s | 36 +++ ...pct_drawSpriteMaskedColorizeM0_cbindings.s | 48 ++++ .../colorReplace/M0/cpct_spriteColorizeM0.asm | 166 ++++++++++++ .../M0/cpct_spriteColorizeM0_asmbindings.s | 36 +++ .../M0/cpct_spriteColorizeM0_cbindings.s | 48 ++++ .../M0/cpct_spriteMaskedColorizeM0.asm | 175 +++++++++++++ .../cpct_spriteMaskedColorizeM0_asmbindings.s | 36 +++ .../cpct_spriteMaskedColorizeM0_cbindings.s | 48 ++++ .../M1/cpct_drawSpriteColorizeM1.asm | 228 ++++++++++++++++ .../cpct_drawSpriteColorizeM1_asmbindings.s | 35 +++ .../M1/cpct_drawSpriteColorizeM1_cbindings.s | 48 ++++ ...cpct_drawSpriteMaskedAlignedColorizeM1.asm | 239 +++++++++++++++++ ...priteMaskedAlignedColorizeM1_asmbindings.s | 36 +++ ...wSpriteMaskedAlignedColorizeM1_cbindings.s | 53 ++++ .../M1/cpct_drawSpriteMaskedColorizeM1.asm | 246 ++++++++++++++++++ ...t_drawSpriteMaskedColorizeM1_asmbindings.s | 36 +++ ...pct_drawSpriteMaskedColorizeM1_cbindings.s | 48 ++++ .../colorReplace/M1/cpct_spriteColorizeM1.asm | 194 ++++++++++++++ .../M1/cpct_spriteColorizeM1_asmbindings.s | 35 +++ .../M1/cpct_spriteColorizeM1_cbindings.s | 48 ++++ .../M1/cpct_spriteMaskedColorizeM1.asm | 205 +++++++++++++++ .../cpct_spriteMaskedColorizeM1_asmbindings.s | 36 +++ .../cpct_spriteMaskedColorizeM1_cbindings.s | 48 ++++ 30 files changed, 2934 insertions(+) create mode 100644 cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteColorizeM0.asm create mode 100644 cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteColorizeM0_asmbindings.s create mode 100644 cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteColorizeM0_cbindings.s create mode 100644 cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteMaskedAlignedColorizeM0.asm create mode 100644 cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteMaskedAlignedColorizeM0_asmbindings.s create mode 100644 cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteMaskedAlignedColorizeM0_cbindings.s create mode 100644 cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteMaskedColorizeM0.asm create mode 100644 cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteMaskedColorizeM0_asmbindings.s create mode 100644 cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteMaskedColorizeM0_cbindings.s create mode 100644 cpctelera/src/sprites/colorReplace/M0/cpct_spriteColorizeM0.asm create mode 100644 cpctelera/src/sprites/colorReplace/M0/cpct_spriteColorizeM0_asmbindings.s create mode 100644 cpctelera/src/sprites/colorReplace/M0/cpct_spriteColorizeM0_cbindings.s create mode 100644 cpctelera/src/sprites/colorReplace/M0/cpct_spriteMaskedColorizeM0.asm create mode 100644 cpctelera/src/sprites/colorReplace/M0/cpct_spriteMaskedColorizeM0_asmbindings.s create mode 100644 cpctelera/src/sprites/colorReplace/M0/cpct_spriteMaskedColorizeM0_cbindings.s create mode 100644 cpctelera/src/sprites/colorReplace/M1/cpct_drawSpriteColorizeM1.asm create mode 100644 cpctelera/src/sprites/colorReplace/M1/cpct_drawSpriteColorizeM1_asmbindings.s create mode 100644 cpctelera/src/sprites/colorReplace/M1/cpct_drawSpriteColorizeM1_cbindings.s create mode 100644 cpctelera/src/sprites/colorReplace/M1/cpct_drawSpriteMaskedAlignedColorizeM1.asm create mode 100644 cpctelera/src/sprites/colorReplace/M1/cpct_drawSpriteMaskedAlignedColorizeM1_asmbindings.s create mode 100644 cpctelera/src/sprites/colorReplace/M1/cpct_drawSpriteMaskedAlignedColorizeM1_cbindings.s create mode 100644 cpctelera/src/sprites/colorReplace/M1/cpct_drawSpriteMaskedColorizeM1.asm create mode 100644 cpctelera/src/sprites/colorReplace/M1/cpct_drawSpriteMaskedColorizeM1_asmbindings.s create mode 100644 cpctelera/src/sprites/colorReplace/M1/cpct_drawSpriteMaskedColorizeM1_cbindings.s create mode 100644 cpctelera/src/sprites/colorReplace/M1/cpct_spriteColorizeM1.asm create mode 100644 cpctelera/src/sprites/colorReplace/M1/cpct_spriteColorizeM1_asmbindings.s create mode 100644 cpctelera/src/sprites/colorReplace/M1/cpct_spriteColorizeM1_cbindings.s create mode 100644 cpctelera/src/sprites/colorReplace/M1/cpct_spriteMaskedColorizeM1.asm create mode 100644 cpctelera/src/sprites/colorReplace/M1/cpct_spriteMaskedColorizeM1_asmbindings.s create mode 100644 cpctelera/src/sprites/colorReplace/M1/cpct_spriteMaskedColorizeM1_cbindings.s diff --git a/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteColorizeM0.asm b/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteColorizeM0.asm new file mode 100644 index 000000000..13d195147 --- /dev/null +++ b/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteColorizeM0.asm @@ -0,0 +1,203 @@ +;;-----------------------------LICENSE NOTICE------------------------------------ +;; This file is part of CPCtelera: An Amstrad CPC Game Engine +;; Copyright (C) 2017 Arnaud Bouche (Arnaud6128) +;; Copyright (C) 2017 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) +;; +;; This program is free software: you can redistribute it and/or modify +;; it under the terms of the GNU Lesser General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU Lesser General Public License for more details. +;; +;; You should have received a copy of the GNU Lesser General Public License +;; along with this program. If not, see <http://www.gnu.org/licenses/>. +;;------------------------------------------------------------------------------- +.module cpct_sprites + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; +;; Function: cpct_drawSpriteColorizeM0 +;; +;; Directly replace a color and draw a sprite to video memory. +;; +;; C Definition: +;; void <cpct_drawSpriteColorizeM0> (void* *sprite*, void* *memory*, <u8> *width*, <u8> *height*, <u8> *oldColor*, <u8> *newColor*) __z88dk_callee; +;; +;; Input Parameters (8 bytes): +;; (2B HL') sprite - Source Sprite Pointer (array of pixel data) +;; (2B DE') memory - Destination video memory pointer +;; (1B C' ) height - Sprite Height in bytes (>0) +;; (1B B' ) width - Sprite Width in *bytes* (Beware, *not* in pixels!) +;; (1B L ) oldColor - Color to replace +;; (1B H ) newColor - New color +;; +;; Assembly call (Input parameters on registers): +;; > call cpct_drawSpriteColorizeM0_asm +;; +;; Parameter Restrictions: +;; * *sprite* must be an array containing sprite's pixels data in screen pixel format. +;; Sprite must be rectangular and all bytes in the array must be consecutive pixels, +;; starting from top-left corner and going left-to-right, top-to-bottom down to the +;; bottom-right corner. Total amount of bytes in pixel array should be *width* x *height*. +;; * *memory* could be any place in memory, inside or outside current video memory. It +;; will be equally treated as video memory (taking into account CPC's video memory +;; disposition). This lets you copy sprites to software or hardware backbuffers, and +;; not only video memory. +;; * *width* must be the width of the sprite *in bytes*. Always remember that the width must be +;; expressed in bytes and *not* in pixels. +;; The correspondence is mode 0 : 1 byte = 2 pixels +;; * *height* must be the height of the sprite in bytes, and must be greater than 0. +;; There is no practical upper limit to this value. Height of a sprite in +;; bytes and pixels is the same value, as bytes only group consecutive pixels in +;; the horizontal space. +;; * *oldColor* must be the index of color (0 to 15) to replace +;; * *newColor* must be the index of the new color (0 to 15) +;; +;; Known limitations: +;; * This function does not do any kind of boundary check or clipping. If you +;; try to draw sprites on the frontier of your video memory or screen buffer +;; if might potentially overwrite memory locations beyond boundaries. This +;; could cause your program to behave erratically, hang or crash. Always +;; take the necessary steps to guarantee that you are drawing inside screen +;; or buffer boundaries. +;; * As this function receives a byte-pointer to memory, it can only +;; draw byte-sized and byte-aligned sprites. This means that the box cannot +;; start on non-byte aligned pixels (like odd-pixels, for instance) and +;; their sizes must be a multiple of a byte (2 in mode 0, 4 in mode 1 and +;; 8 in mode 2). +;; * This function *will not work from ROM*, as it uses self-modifying code. +;; * This function requires the CPC firmware to be DISABLED. Otherwise, random crashes might happen due to side effects. +;; +;; Destroyed Register values: +;; AF, BC, DE, HL, BC', DE', HL', IX +;; +;; Required memory: +;; C-bindings - 118 bytes +;; ASM-bindings - 108 bytes +;; +;; Time Measures: +;; (start code) +;; Case | microSecs (us) | CPU Cycles +;; ---------------------------------------------------------------- +;; | 29 + (62 + 23W)H | 116 + (248 + 92W)H +;; ---------------------------------------------------------------- +;; W=2,H=16 | 1757 | 7028 +;; W=4,H=32 | 4957 | 19828 +;; ---------------------------------------------------------------- +;; Asm saving | -16 | -64 +;; ---------------------------------------------------------------- +;; (end code) +;; W = *width* in bytes, H = *height* in bytes, HH = [(H-1)/8] +;; +;; Credits: +;; Original routine optimized by @Docent and discussed in CPCWiki : +;; http://www.cpcwiki.eu/forum/programming/cpctelera-colorize-sprite/ +;; +;; Thanks to all of them for their help and support. +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +.globl dc_mode0_ct + +;; Macro to convert Pixel to xAxC xBxD format +.macro convertPixel + ;; From cpct_px2byteM0 + ld bc, #dc_mode0_ct ;; [3] BC points to conversion table (dc_mode0_ct) + + ;; Compute BC += A + add c ;; [1] | C += A + ld c, a ;; [1] | + sub a ;; [1] A = 0 (preserving Carry Flag) + adc b ;; [1] | B += Carry + ld b, a ;; [1] | + + ;; A = *(BC + A) + ld a, (bc) ;; [2] A = Value stored at the table pointed by BC +.endm + + ;; Convert newColor to pixel format (E) + ld a, h ;; [1] A = H new color index + convertPixel ;; [10] | Convert into A + ld e, a ;; [1] | E = A new color : xAxC xBxD + + ;; Convert oldColor to pixel format (D) + ld a, l ;; [1] A = L old color index + convertPixel ;; [10] | Convert into A + ld d, a ;; [1] | D = A old color : xAxC xBxD + + ld c, #0x55 ;; [2] C = Mask to get pixel A : xAxC xBxD + + exx ;; [1] Switch to Alternate registers + + ld__ixl_c ;; [1] IXL = C (Width) + ld c, b ;; [1] C = B (Height) + +convertLoop: + ld (startLine), de ;; [6] Store DE start line (DestMem) + ld__b_ixl ;; [2] B = IXL (Sprite Width) + +lineLoop: + ld a, (hl) ;; [2] A = (HL) current Byte of sprite + exx ;; [1] Switch to Default registers + + ld l, a ;; [1] L = A current Byte of sprite : ABAB ABAB + and c ;; [2] A |= C (C = 0x55) : xBxB xBxB + + cp d ;; [1] Test if pixel (A) is the old colour to be replaced (D) + jr nz, readPixelA ;; [2/3] If not equal go to next pixel + ld a, e ;; [1] else A = new colour to set (E) + +;; Pixel Mode 0 = ABAB ABAB +readPixelA: + ld h, a ;; [1] H = A (current colorized sprite) : xBxB xBxB + ld a, l ;; [1] L = A current Byte of sprite : ABAB ABAB + rrca ;; [1] A (current byte of sprite) >> 1 : ABAB ABAB -> xABA BABA + and c ;; [2] A |= Mask (0x55) : xAxA xAxA + + cp d ;; [1] Test if pixel (A) is the old colour to be replaced (D) + jr nz, readPixelB ;; [2/3] If not equal go to next pixel + ld a, e ;; [1] else A = new colour to set (E) + +readPixelB: + rlca ;; [1] A = xAxA xAxA << 1 : AxAx AxAx + or h ;; [1] A |= H (xBxB xBxB) : ABAB ABAB + + exx ;; [1] Switch to Alternate registers + +drawByte: + ld (de), a ;; [2] Update current sprite byte with pixels + inc hl ;; [2] Next byte sprite source + inc de ;; [2] Next byte sprite colorized + djnz lineLoop ;; [3] Decrement B (Width) if B != 0 goto lineLoop + + dec c ;; [1] Decrement C (Height) + jr z, end ;; [2/3] If C == O goto end + +startLine = .+1 ;; Placeholder for the Start line adress + ld de, #0000 ;; [3] DE = Start Line + + ld a, d ;; [1] Start of next pixel line normally is 0x0800 bytes away. + add #0x08 ;; [2] so we add it to DE (just by adding 0x08 to D) + ld d, a ;; [1] + and #0x38 ;; [2] We check if we have crossed memory boundary (every 8 pixel lines).. + + jr nz, convertLoop ;; [2/3] .. by checking the 4 bits that identify present memory line. + ;; .... If 0, we have crossed boundaries + +dms_sprite_8bit_boundary_crossed: + ld a, e ;; [1] DE = DE + 0xC050h + add #0x50 ;; [2] -- Relocate DE pointer to the start of the next pixel line: + ld e, a ;; [1] -- DE is moved forward 3 memory banks plus 50 bytes (4000h * 3) + ld a, d ;; [1] -- which effectively is the same as moving it 1 bank backwards and then + adc #0xC0 ;; [2] -- 50 bytes forwards (which is what we want to move it to the next pixel line) + ld d, a ;; [1] -- Calculations are made with 8 bit maths as it is faster than other alternatives here + + jr convertLoop ;; [3] Jump to continue with next pixel line + +end: + ;; Return is included in bindings + + diff --git a/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteColorizeM0_asmbindings.s b/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteColorizeM0_asmbindings.s new file mode 100644 index 000000000..d5930a9aa --- /dev/null +++ b/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteColorizeM0_asmbindings.s @@ -0,0 +1,36 @@ +;;-----------------------------LICENSE NOTICE------------------------------------ +;; This file is part of CPCtelera: An Amstrad CPC Game Engine +;; Copyright (C) 2017 Arnaud Bouche (Arnaud6128) +;; Copyright (C) 2017 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) +;; +;; This program is free software: you can redistribute it and/or modify +;; it under the terms of the GNU Lesser General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU Lesser General Public License for more details. +;; +;; You should have received a copy of the GNU Lesser General Public License +;; along with this program. If not, see <http://www.gnu.org/licenses/>. +;;------------------------------------------------------------------------------- +.module cpct_sprites + +.include "../../../macros/cpct_undocumentedOpcodes.s" + +;; +;; ASM bindings for <cpct_drawSpriteColorizeM0> +;; +cpct_drawSpriteColorizeM0_asm:: ;; Assembly entry point + + ;; GET Parameters from the stack + ld (dms_restore_ix + 2), ix ;; [6] Save IX to restore it before returning + pop hl ;; [3] HL = Return Address + +;;.include /cpct_drawSpriteColorizeM0.asm/ + +dms_restore_ix: + ld ix, #0000 ;; [4] Restore IX before returning + ret ;; [3] Return to caller \ No newline at end of file diff --git a/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteColorizeM0_cbindings.s b/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteColorizeM0_cbindings.s new file mode 100644 index 000000000..ac5d57084 --- /dev/null +++ b/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteColorizeM0_cbindings.s @@ -0,0 +1,48 @@ +;;-----------------------------LICENSE NOTICE------------------------------------ +;; This file is part of CPCtelera: An Amstrad CPC Game Engine +;; Copyright (C) 2017 Arnaud Bouche (Arnaud6128) +;; Copyright (C) 2017 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) +;; +;; This program is free software: you can redistribute it and/or modify +;; it under the terms of the GNU Lesser General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU Lesser General Public License for more details. +;; +;; You should have received a copy of the GNU Lesser General Public License +;; along with this program. If not, see <http://www.gnu.org/licenses/>. +;;------------------------------------------------------------------------------- +.module cpct_sprites + +.include "../../../macros/cpct_undocumentedOpcodes.s" + +;; +;; C bindings for <cpct_drawSpriteColorizeM0> +;; +;; 33 us, 10 bytes +;; +_cpct_drawSpriteColorizeM0:: + + ;; GET Parameters from the stack + ld (dms_restore_ix + 2), ix ;; [6] Save IX to restore it before returning + pop hl ;; [3] HL = Return Address + + exx + pop hl ;; [3] HL' = Source address (Sprite) + pop de ;; [3] DE' = Destination Memory + pop bc ;; [5] BC' = (B = Sprite Height, C = Width) + exx + + ex (sp), hl ;; [6] HL = (H = newColor, L = oldColor) + ;; ... and leave Return Address at (SP) as we don't need to restore + ;; ... stack status because callin convention is __z88dk_callee + +.include /cpct_drawSpriteColorizeM0.asm/ + +dms_restore_ix: + ld ix, #0000 ;; [4] Restore IX before returning + ret ;; [3] Return to caller \ No newline at end of file diff --git a/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteMaskedAlignedColorizeM0.asm b/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteMaskedAlignedColorizeM0.asm new file mode 100644 index 000000000..21308854d --- /dev/null +++ b/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteMaskedAlignedColorizeM0.asm @@ -0,0 +1,215 @@ +;;-----------------------------LICENSE NOTICE------------------------------------ +;; This file is part of CPCtelera: An Amstrad CPC Game Engine +;; Copyright (C) 2017 Arnaud Bouche (Arnaud6128) +;; Copyright (C) 2017 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) +;; +;; This program is free software: you can redistribute it and/or modify +;; it under the terms of the GNU Lesser General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU Lesser General Public License for more details. +;; +;; You should have received a copy of the GNU Lesser General Public License +;; along with this program. If not, see <http://www.gnu.org/licenses/>. +;;------------------------------------------------------------------------------- +.module cpct_sprites + +.globl dc_mode0_ct + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; +;; Function: cpct_drawSpriteMaskedAlignedColorizeM0 +;; +;; Directly replace a color and draw a sprite Masked Aligned to video memory. +;; +;; C Definition: +;; void <cpct_drawSpriteMaskedAlignedColorizeM0> (void* *sprite*, void* *memory*, <u8> *width*, <u8> *height*, +;; <u8> *oldColor*, <u8> *newColor*, <u8*> *pmasktable*) __z88dk_callee; +;; +;; Input Parameters (10 bytes): +;; (2B HL') sprite - Source Sprite Pointer (array of pixel data) +;; (2B DE') memory - Destination video memory pointer +;; (1B C' ) height - Sprite Height in bytes (>0) +;; (1B B' ) width - Sprite Width in *bytes* (Beware, *not* in pixels!) +;; (1B E ) oldColor - Color to replace +;; (1B D ) newColor - New color +;; (2B HL) pmasktable - Pointer to the aligned mask table used to create transparency +;; +;; Assembly call (Input parameters on registers): +;; > call cpct_drawSpriteMaskedAlignedColorizeM0_asm +;; +;; Parameter Restrictions: +;; * *sprite* must be an array containing sprite's pixels data in screen pixel format +;; Sprite must be rectangular and all bytes in the array must be consecutive pixels, +;; starting from top-left corner and going left-to-right, top-to-bottom down to the +;; bottom-right corner. Total amount of bytes in pixel array should be *width* x *height*. +;; * *memory* could be any place in memory, inside or outside current video memory. It +;; will be equally treated as video memory (taking into account CPC's video memory +;; disposition). This lets you copy sprites to software or hardware backbuffers, and +;; not only video memory. +;; * *width* must be the width of the sprite *in bytes*. Always remember that the width must be +;; expressed in bytes and *not* in pixels. +;; The correspondence is mode 0 : 1 byte = 2 pixels +;; * *height* must be the height of the sprite in bytes, and must be greater than 0. +;; There is no practical upper limit to this value. Height of a sprite in +;; bytes and pixels is the same value, as bytes only group consecutive pixels in +;; the horizontal space. +;; * *oldColor* must be the index of color (0 to 15) to replace +;; * *newColor* must be the index of the new color (0 to 15) +;; +;; Known limitations: +;; * This function does not do any kind of boundary check or clipping. If you +;; try to draw sprites on the frontier of your video memory or screen buffer +;; if might potentially overwrite memory locations beyond boundaries. This +;; could cause your program to behave erratically, hang or crash. Always +;; take the necessary steps to guarantee that you are drawing inside screen +;; or buffer boundaries. +;; * As this function receives a byte-pointer to memory, it can only +;; draw byte-sized and byte-aligned sprites. This means that the box cannot +;; start on non-byte aligned pixels (like odd-pixels, for instance) and +;; their sizes must be a multiple of a byte (2 in mode 0, 4 in mode 1 and +;; 8 in mode 2). +;; * This function *will not work from ROM*, as it uses self-modifying code. +;; * This function requires the CPC firmware to be DISABLED. Otherwise, random crashes might happen due to side effects. +;; +;; Destroyed Register values: +;; AF, BC, DE, HL, BC', DE', HL', IX +;; +;; Required memory: +;; C-bindings - 112 bytes +;; ASM-bindings - 96 bytes +;; +;; Time Measures: +;; (start code) +;; Case | microSecs (us) | CPU Cycles +;; ---------------------------------------------------------------- +;; | 32 + (58 + 20W)H | 128 + (232 + 80W)H +;; ---------------------------------------------------------------- +;; W=2,H=16 | 1600 | 6400 +;; W=4,H=32 | 4448 | 17792 +;; ---------------------------------------------------------------- +;; Asm saving | -16 | -64 +;; ---------------------------------------------------------------- +;; (end code) +;; W = *width* in bytes, H = *height* in bytes, HH = [(H-1)/8] +;; +;; Credits: +;; Original routine optimized by @Docent and discussed in CPCWiki : +;; http://www.cpcwiki.eu/forum/programming/cpctelera-colorize-sprite/ +;; +;; Thanks to all of them for their help and support. +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;; Macro to convert Pixel to xAxC xBxD format +.macro convertPixel + ;; From cpct_px2byteM0 + ld bc, #dc_mode0_ct ;; [3] BC points to conversion table (dc_mode0_ct) + + ;; Compute BC += A + add c ;; [1] | C += A + ld c, a ;; [1] | + sub a ;; [1] A = 0 (preserving Carry Flag) + adc b ;; [1] | B += Carry + ld b, a ;; [1] | + + ;; A = *(BC + A) + ld a, (bc) ;; [2] A = Value stored at the table pointed by BC +.endm + + ;; Convert newColor to pixel format (E) + ld a, h ;; [1] A = H new color index + convertPixel ;; [10] | Convert into A + ld e, a ;; [1] | E = A new color : xAxC xBxD + + ;; Convert oldColor to pixel format (D) + ld a, l ;; [1] A = L old color index + convertPixel ;; [10] | Convert into A + ld b, d + ld d, a ;; [1] | D = A old color : xAxC xBxD + + ld c, #0x55 ;; [2] C = Mask to get pixel A : xAxC xBxD + exx ;; [1] Switch to Alternate registers + + ld__ixl_c ;; [1] IXL = C (Width) + ld c, b ;; [1] C = B (Height) + +convertLoop: + push de ;; [4] Store DE start line (DestMem) + ld__b_ixl ;; [2] B = IXL (Sprite Width) + +lineLoop: + ld a, (hl) ;; [2] A = (HL) current Byte of sprite + exx ;; [1] Switch to Default registers + + ld l, a ;; [1] L = A current Byte of sprite : ABAB ABAB + and c ;; [2] A |= C (C = 0x55) : xBxB xBxB + + cp d ;; [1] Test if pixel (A) is the old colour to be replaced (D) + jr nz, readPixelA ;; [2/3] If not equal go to next pixel + ld a, e ;; [1] else A = new colour to set (E) + +;; Pixel Mode 0 = ABAB ABAB +readPixelA: + ld h, a ;; [1] H = A (current colorized sprite) : xBxB xBxB + ld a, l ;; [1] L = A current Byte of sprite : ABAB ABAB + rrca ;; [1] A (current byte of sprite) >> 1 : ABAB ABAB -> xABA BABA + and c ;; [2] A |= Mask (0x55) : xAxA xAxA + + cp d ;; [1] Test if pixel (A) is the old colour to be replaced (D) + jr nz, readPixelB ;; [2/3] If not equal go to next pixel + ld a, e ;; [1] else A = new colour to set (E) + +readPixelB: + rlca ;; [1] A = xAxA xAxA << 1 : AxAx AxAx + or h ;; [1] A |= H (xBxB xBxB) : ABAB ABAB + +drawByte: + ld h, b ;; [1] H = B (Masked table adress High Byte) + ld l, a ;; [1] Access mask table element (table must be 256-byte aligned) + exx ;; [1] Switch to Alternate registers + + ld a, (de) ;; [2] Get the value of the byte of the screen where we are going to draw + exx ;; [1] Switch to Default registers + + and (hl) ;; [2] Erase background part that is to be overwritten (Mask step 1) + or l ;; [1] Add up background and sprite information in one byte (Mask step 2) + exx ;; [1] Switch to Alternate registers + + ld (de), a ;; [2] Save modified background + sprite data information into memory + + inc hl ;; [2] Next byte sprite source + inc de ;; [2] Next byte sprite colorized + djnz lineLoop ;; [3] Decrement B (Width) if B != 0 goto lineLoop + + dec c ;; [1] Decrement C (Height) + jr z, end ;; [2/3] If C == O goto end + + pop de ;; [3] Restore DE start line (DestMem) + + ld a, d ;; [1] Start of next pixel line normally is 0x0800 bytes away. + add #0x08 ;; [2] so we add it to DE (just by adding 0x08 to D) + ld d, a ;; [1] + and #0x38 ;; [2] We check if we have crossed memory boundary (every 8 pixel lines).. + + jr nz, convertLoop ;; [2/3] .. by checking the 4 bits that identify present memory line. + ;; .... If 0, we have crossed boundaries + +dms_sprite_8bit_boundary_crossed: + ld a, e ;; [1] DE = DE + 0xC050h + add #0x50 ;; [2] -- Relocate DE pointer to the start of the next pixel line: + ld e, a ;; [1] -- DE is moved forward 3 memory banks plus 50 bytes (4000h * 3) + ld a, d ;; [1] -- which effectively is the same as moving it 1 bank backwards and then + adc #0xC0 ;; [2] -- 50 bytes forwards (which is what we want to move it to the next pixel line) + ld d, a ;; [1] -- Calculations are made with 8 bit maths as it is faster than other alternatives here + + jr convertLoop ;; [3] Jump to continue with next pixel line + +end: + pop de ;; [3] Empty stack by getting last element (DestMem) + ;; Return is included in bindings + + diff --git a/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteMaskedAlignedColorizeM0_asmbindings.s b/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteMaskedAlignedColorizeM0_asmbindings.s new file mode 100644 index 000000000..7828b8736 --- /dev/null +++ b/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteMaskedAlignedColorizeM0_asmbindings.s @@ -0,0 +1,36 @@ +;;-----------------------------LICENSE NOTICE------------------------------------ +;; This file is part of CPCtelera: An Amstrad CPC Game Engine +;; Copyright (C) 2017 Arnaud Bouche (Arnaud6128) +;; Copyright (C) 2017 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) +;; +;; This program is free software: you can redistribute it and/or modify +;; it under the terms of the GNU Lesser General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU Lesser General Public License for more details. +;; +;; You should have received a copy of the GNU Lesser General Public License +;; along with this program. If not, see <http://www.gnu.org/licenses/>. +;;------------------------------------------------------------------------------- +.module cpct_sprites + +.include "../../../macros/cpct_undocumentedOpcodes.s" + +;; +;; ASM bindings for <cpct_drawSpriteMaskedAlignedColorizeM0> +;; +cpct_drawSpriteMaskedAlignedColorizeM0_asm:: ;; Assembly entry point + + ;; GET Parameters from the stack + ld (dms_restore_ix + 2), ix ;; [6] Save IX to restore it before returning + pop hl ;; [3] HL = Return Address + +.include /cpct_drawSpriteMaskedAlignedColorizeM0.asm/ + +dms_restore_ix: + ld ix, #0000 ;; [4] Restore IX before returning + ret ;; [3] Return to caller \ No newline at end of file diff --git a/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteMaskedAlignedColorizeM0_cbindings.s b/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteMaskedAlignedColorizeM0_cbindings.s new file mode 100644 index 000000000..001ae99c3 --- /dev/null +++ b/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteMaskedAlignedColorizeM0_cbindings.s @@ -0,0 +1,52 @@ +;;-----------------------------LICENSE NOTICE------------------------------------ +;; This file is part of CPCtelera: An Amstrad CPC Game Engine +;; Copyright (C) 2017 Arnaud Bouche (Arnaud6128) +;; Copyright (C) 2017 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) +;; +;; This program is free software: you can redistribute it and/or modify +;; it under the terms of the GNU Lesser General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU Lesser General Public License for more details. +;; +;; You should have received a copy of the GNU Lesser General Public License +;; along with this program. If not, see <http://www.gnu.org/licenses/>. +;;------------------------------------------------------------------------------- +.module cpct_sprites + +.include "../../../macros/cpct_undocumentedOpcodes.s" + +;; +;; C bindings for <cpct_drawSpriteMaskedAlignedColorizeM0> +;; +;; 39 us, 16 bytes +;; +_cpct_drawSpriteMaskedAlignedColorizeM0:: + + ;; GET Parameters from the stack + ld (dms_restore_ix + 2), ix ;; [6] Save IX to restore it before returning + pop hl ;; [3] HL = Return Address + + exx ;; [1] Switch to Alternate registers + pop hl ;; [3] HL' = Source address (Sprite) + pop de ;; [3] DE' = Destination Memory + pop bc ;; [5] BC' = (B = Sprite Height, C = Width) + + exx ;; [1] Switch to Default registers + pop de ;; [3] DE = (D = newColor, E = oldColor) + + ex (sp), hl ;; [6] HL = Table Mask address + ;; ... and leave Return Address at (SP) as we don't need to restore + ;; ... stack status because callin convention is __z88dk_callee + + ex de, hl ;; [1] HL <-> DE + +.include /cpct_drawSpriteMaskedAlignedColorizeM0.asm/ + +dms_restore_ix: + ld ix, #0000 ;; [4] Restore IX before returning + ret ;; [3] Return to caller \ No newline at end of file diff --git a/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteMaskedColorizeM0.asm b/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteMaskedColorizeM0.asm new file mode 100644 index 000000000..eb9fd04e4 --- /dev/null +++ b/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteMaskedColorizeM0.asm @@ -0,0 +1,216 @@ +;;-----------------------------LICENSE NOTICE------------------------------------ +;; This file is part of CPCtelera: An Amstrad CPC Game Engine +;; Copyright (C) 2017 Arnaud Bouche +;; Copyright (C) 2017 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) +;; +;; This program is free software: you can redistribute it and/or modify +;; it under the terms of the GNU Lesser General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU Lesser General Public License for more details. +;; +;; You should have received a copy of the GNU Lesser General Public License +;; along with this program. If not, see <http://www.gnu.org/licenses/>. +;;------------------------------------------------------------------------------- +.module cpct_sprites + +.globl dc_mode0_ct + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; +;; Function: cpct_drawSpriteMaskedColorizeM0 +;; +;; Directly replace a color and draw a sprite Masked to video memory. +;; +;; C Definition: +;; void <cpct_drawSpriteMaskedColorizeM0> (void* *sprite*, void* *memory*, <u8> *width*, <u8> *height*, <u8> *oldColor*, <u8> *newColor*) __z88dk_callee; +;; +;; Input Parameters (8 bytes): +;; (2B HL') sprite - Source Sprite Pointer (array of pixel data) +;; (2B DE') memory - Destination video memory pointer +;; (1B C' ) height - Sprite Height in bytes (>0) +;; (1B B' ) width - Sprite Width in *bytes* (Beware, *not* in pixels!) +;; (1B L ) oldColor - Color to replace +;; (1B H ) newColor - New color +;; +;; Assembly call (Input parameters on registers): +;; > call cpct_drawSpriteMaskedColorizeM0_asm +;; +;; Parameter Restrictions: +;; * *sprite* must be an array containing sprite's pixels data in screen pixel format +;; along with mask data. Each mask byte will contain enabled bits as those that should +;; be picked from the background (transparent) and disabled bits for those that will +;; be printed from sprite colour data. Each mask data byte must precede its associated +;; colour data byte. +;; Sprite must be rectangular and all bytes in the array must be consecutive pixels, +;; starting from top-left corner and going left-to-right, top-to-bottom down to the +;; bottom-right corner. Total amount of bytes in pixel array should be +;; 2 x *width* x *height* (mask data doubles array size). +;; * *memory* could be any place in memory, inside or outside current video memory. It +;; will be equally treated as video memory (taking into account CPC's video memory +;; disposition). This lets you copy sprites to software or hardware backbuffers, and +;; not only video memory. +;; * *width* must be the width of the sprite *in bytes*. Always remember that the width must be +;; expressed in bytes and *not* in pixels. +;; The correspondence is mode 0 : 1 byte = 2 pixels +;; * *height* must be the height of the sprite in bytes, and must be greater than 0. +;; There is no practical upper limit to this value. Height of a sprite in +;; bytes and pixels is the same value, as bytes only group consecutive pixels in +;; the horizontal space. +;; * *oldColor* must be the index of color (0 to 15) to replace +;; * *newColor* must be the index of the new color (0 to 15) +;; +;; Known limitations: +;; * This function does not do any kind of boundary check or clipping. If you +;; try to draw sprites on the frontier of your video memory or screen buffer +;; if might potentially overwrite memory locations beyond boundaries. This +;; could cause your program to behave erratically, hang or crash. Always +;; take the necessary steps to guarantee that you are drawing inside screen +;; or buffer boundaries. +;; * As this function receives a byte-pointer to memory, it can only +;; draw byte-sized and byte-aligned sprites. This means that the box cannot +;; start on non-byte aligned pixels (like odd-pixels, for instance) and +;; their sizes must be a multiple of a byte (2 in mode 0, 4 in mode 1 and +;; 8 in mode 2). +;; * This function *will not work from ROM*, as it uses self-modifying code. +;; * This function requires the CPC firmware to be DISABLED. Otherwise, random crashes might happen due to side effects. +;; +;; Destroyed Register values: +;; AF, BC, DE, HL, BC', DE', HL', IX +;; +;; Required memory: +;; C-bindings - 115 bytes +;; ASM-bindings - 102 bytes +;; +;; Time Measures: +;; (start code) +;; Case | microSecs (us) | CPU Cycles +;; ---------------------------------------------------------------- +;; Best | 29 + (50 + 36W)H | 116 + (200 + 144W)H +;; ---------------------------------------------------------------- +;; W=2,H=16 | 1981 | 7924 +;; W=4,H=32 | 6237 | 24948 +;; ---------------------------------------------------------------- +;; Asm saving | -16 | -64 +;; ---------------------------------------------------------------- +;; (end code) +;; W = *width* in bytes, H = *height* in bytes, HH = [(H-1)/8] +;; +;; Credits: +;; Original routine optimized by @Docent and discussed in CPCWiki : +;; http://www.cpcwiki.eu/forum/programming/cpctelera-colorize-sprite/ +;; +;; Thanks to all of them for their help and support. +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;; Macro to convert Pixel to xAxC xBxD format +.macro convertPixel + ;; From cpct_px2byteM0 + ld bc, #dc_mode0_ct ;; [3] BC points to conversion table (dc_mode0_ct) + + ;; Compute BC += A + add c ;; [1] | C += A + ld c, a ;; [1] | + sub a ;; [1] A = 0 (preserving Carry Flag) + adc b ;; [1] | B += Carry + ld b, a ;; [1] | + + ;; A = *(BC + A) + ld a, (bc) ;; [2] A = Value stored at the table pointed by BC +.endm + + ;; Convert newColor to pixel format (E) + ld a, h ;; [1] A = H new color index + convertPixel ;; [10] | Convert into A + ld e, a ;; [1] | E = A new color : xAxC xBxD + + ;; Convert oldColor to pixel format (D) + ld a, l ;; [1] A = L old color index + convertPixel ;; [10] | Convert into A + ld d, a ;; [1] | D = A old color : xAxC xBxD + + ld c, #0x55 ;; [2] C = Mask to get pixel A : xAxC xBxD + + exx ;; [1] Switch to Alternate registers + + ld__ixl_c ;; [1] IXL = C (Width) + ld c, b ;; [1] C = B (Height) + +convertLoop: + ld (startLine), de ;; [6] Store DE start line (DestMem) + ld__b_ixl ;; [2] B = IXL (Sprite Width) + +lineLoop: + inc hl ;; [2] Next byte sprite Color source + ld a, (hl) ;; [2] A = (HL) current Byte of sprite Color + dec hl ;; [2] Previous byte sprite Mask source + + exx ;; [1] Switch to Default registers + + ld l, a ;; [1] L = A current Byte of sprite : ABAB ABAB + and c ;; [2] A |= C (C = 0x55) : xBxB xBxB + + cp d ;; [1] Test if pixel (A) is the old colour to be replaced (D) + jr nz, readPixelA ;; [2/3] If not equal go to next pixel + ld a, e ;; [1] else A = new colour to set (E) + +;; Pixel Mode 0 = ABAB ABAB +readPixelA: + ld h, a ;; [1] H = A (current colorized sprite) : xBxB xBxB + ld a, l ;; [1] L = A current Byte of sprite : ABAB ABAB + rrca ;; [1] A (current byte of sprite) >> 1 : ABAB ABAB -> xABA BABA + and c ;; [2] A |= Mask (0x55) : xAxA xAxA + + cp d ;; [1] Test if pixel (A) is the old colour to be replaced (D) + jr nz, readPixelB ;; [2/3] If not equal go to next pixel + ld a, e ;; [1] else A = new colour to set (E) + +readPixelB: + rlca ;; [1] A = xAxA xAxA << 1 : AxAx AxAx + or h ;; [1] A |= H (xBxB xBxB) : ABAB ABAB + +drawByte: + exx ;; [1] Switch to Alternate registers + ld (sprite_color), a ;; [4] sprite_color = A (Sprite Byte) + + ld a, (de) ;; [2] Get next background byte into A + and (hl) ;; [2] Erase background part that is to be overwritten (Mask step 1) + inc hl ;; [3] HL += 1 => Point HL to Sprite Colour information +sprite_color = .+1 ;; Placeholder for the Sprite Color computed + or #00 ;; [2] Add up background and sprite information in one byte (Mask step 2) + ld (de), a ;; [2] Save modified background + sprite data information into memory + + inc hl ;; [2] Next byte sprite source + inc de ;; [2] Next byte Dest Memory + djnz lineLoop ;; [3] Decrement B (Width) if B != 0 goto lineLoop + + dec c ;; [1] Decrement C (Height) + jr z, end ;; [2/3] If C == O goto end + +startLine = .+1 ;; Placeholder for the Start line adress + ld de, #0000 ;; [3] DE = Start Line + + ld a, d ;; [1] Start of next pixel line normally is 0x0800 bytes away. + add #0x08 ;; [2] so we add it to DE (just by adding 0x08 to D) + ld d, a ;; [1] + and #0x38 ;; [2] We check if we have crossed memory boundary (every 8 pixel lines).. + + jr nz, convertLoop ;; [2/3] .. by checking the 4 bits that identify present memory line. + ;; .... If 0, we have crossed boundaries + +dms_sprite_8bit_boundary_crossed: + ld a, e ;; [1] DE = DE + 0xC050h + add #0x50 ;; [2] -- Relocate DE pointer to the start of the next pixel line: + ld e, a ;; [1] -- DE is moved forward 3 memory banks plus 50 bytes (4000h * 3) + ld a, d ;; [1] -- which effectively is the same as moving it 1 bank backwards and then + adc #0xC0 ;; [2] -- 50 bytes forwards (which is what we want to move it to the next pixel line) + ld d, a ;; [1] -- Calculations are made with 8 bit maths as it is faster than other alternatives here + + jr convertLoop ;; [3] Jump to continue with next pixel line + +end: + ;; Return is included in bindings \ No newline at end of file diff --git a/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteMaskedColorizeM0_asmbindings.s b/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteMaskedColorizeM0_asmbindings.s new file mode 100644 index 000000000..1a40a3186 --- /dev/null +++ b/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteMaskedColorizeM0_asmbindings.s @@ -0,0 +1,36 @@ +;;-----------------------------LICENSE NOTICE------------------------------------ +;; This file is part of CPCtelera: An Amstrad CPC Game Engine +;; Copyright (C) 2017 Arnaud Bouche (Arnaud6128) +;; Copyright (C) 2017 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) +;; +;; This program is free software: you can redistribute it and/or modify +;; it under the terms of the GNU Lesser General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU Lesser General Public License for more details. +;; +;; You should have received a copy of the GNU Lesser General Public License +;; along with this program. If not, see <http://www.gnu.org/licenses/>. +;;------------------------------------------------------------------------------- +.module cpct_sprites + +.include "../../../macros/cpct_undocumentedOpcodes.s" + +;; +;; ASM bindings for <cpct_drawSpriteMaskedColorizeM0> +;; +cpct_drawSpriteMaskedColorizeM0_asm:: ;; Assembly entry point + + ;; GET Parameters from the stack + ld (dms_restore_ix + 2), ix ;; [6] Save IX to restore it before returning + pop hl ;; [3] HL = Return Address + +.include /cpct_drawSpriteMaskedColorizeM0.asm/ + +dms_restore_ix: + ld ix, #0000 ;; [4] Restore IX before returning + ret ;; [3] Return to caller \ No newline at end of file diff --git a/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteMaskedColorizeM0_cbindings.s b/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteMaskedColorizeM0_cbindings.s new file mode 100644 index 000000000..c39a879a4 --- /dev/null +++ b/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteMaskedColorizeM0_cbindings.s @@ -0,0 +1,48 @@ +;;-----------------------------LICENSE NOTICE------------------------------------ +;; This file is part of CPCtelera: An Amstrad CPC Game Engine +;; Copyright (C) 2017 Arnaud Bouche (Arnaud6128) +;; Copyright (C) 2017 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) +;; +;; This program is free software: you can redistribute it and/or modify +;; it under the terms of the GNU Lesser General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU Lesser General Public License for more details. +;; +;; You should have received a copy of the GNU Lesser General Public License +;; along with this program. If not, see <http://www.gnu.org/licenses/>. +;;------------------------------------------------------------------------------- +.module cpct_sprites + +.include "../../../macros/cpct_undocumentedOpcodes.s" + +;; +;; C bindings for <cpct_drawSpriteMaskedColorizeM0> +;; +;; 33 us, 13 bytes +;; +_cpct_drawSpriteMaskedColorizeM0:: + + ;; GET Parameters from the stack + ld (dms_restore_ix + 2), ix ;; [6] Save IX to restore it before returning + pop hl ;; [3] HL = Return Address + + exx + pop hl ;; [3] HL' = Source address (Sprite) + pop de ;; [3] DE' = Destination Memory + pop bc ;; [5] BC' = (B = Sprite Height, C = Width) + exx + + ex (sp), hl ;; [6] HL = (H = newColor, L = oldColor) + ;; ... and leave Return Address at (SP) as we don't need to restore + ;; ... stack status because callin convention is __z88dk_callee + +.include /cpct_drawSpriteMaskedColorizeM0.asm/ + +dms_restore_ix: + ld ix, #0000 ;; [4] Restore IX before returning + ret ;; [3] Return to caller \ No newline at end of file diff --git a/cpctelera/src/sprites/colorReplace/M0/cpct_spriteColorizeM0.asm b/cpctelera/src/sprites/colorReplace/M0/cpct_spriteColorizeM0.asm new file mode 100644 index 000000000..52f433ba3 --- /dev/null +++ b/cpctelera/src/sprites/colorReplace/M0/cpct_spriteColorizeM0.asm @@ -0,0 +1,166 @@ +;;-----------------------------LICENSE NOTICE------------------------------------ +;; This file is part of CPCtelera: An Amstrad CPC Game Engine +;; Copyright (C) 2017 Arnaud Bouche +;; Copyright (C) 2017 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) +;; +;; This program is free software: you can redistribute it and/or modify +;; it under the terms of the GNU Lesser General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU Lesser General Public License for more details. +;; +;; You should have received a copy of the GNU Lesser General Public License +;; along with this program. If not, see <http://www.gnu.org/licenses/>. +;;------------------------------------------------------------------------------- +.module cpct_sprites + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; +;; Function: cpct_spriteColorizeM0 +;; +;; Replace a color in a sprite and copy to another or the same sprite. +;; +;; C Definition: +;; void <cpct_spriteColorizeM0> (void* *sprite*, void* *spriteColor*, <u8> *width*, <u8> *height*, <u8> *oldColor*, <u8> *newColor*) __z88dk_callee; +;; +;; Input Parameters (6 bytes): +;; (2B HL') sprite - Source Sprite Pointer (array of pixel data) +;; (2B DE') spriteColor - Destination Sprite Pointer (can be also the Source Sprite) (array of pixel data) +;; (1B C' ) height - Sprite Height in bytes (>0) +;; (1B B' ) width - Sprite Width in *bytes* (Beware, *not* in pixels!) +;; (1B L ) oldColor - Color to replace +;; (1B H ) newColor - New color +;; +;; Assembly call (Input parameters on registers): +;; > call cpct_spriteColorizeM0_asm +;; +;; Parameter Restrictions: +;; * *sprite* must be an array containing sprite's pixels data in screen pixel format. +;; Sprite must be rectangular and all bytes in the array must be consecutive pixels, +;; starting from top-left corner and going left-to-right, top-to-bottom down to the +;; bottom-right corner. Total amount of bytes in pixel array should be *width* x *height*. +;; * *spriteColor* must be an array containing the new sprite's pixels data with the new color. +;; * *width* must be the width of the sprite *in bytes*. Always remember that the width must be +;; expressed in bytes and *not* in pixels. +;; The correspondence is mode 0 : 1 byte = 2 pixels +;; * *height* must be the height of the sprite in bytes, and must be greater than 0. +;; There is no practical upper limit to this value. Height of a sprite in +;; bytes and pixels is the same value, as bytes only group consecutive pixels in +;; the horizontal space. +;; * *oldColor* must be the index of color (0 to 15) to replace +;; * *newColor* must be the index of the new color (0 to 15) +;; +;; Known limitations: +;; * This function *will not work from ROM*, as it uses self-modifying code. +;; * This function requires the CPC firmware to be DISABLED. Otherwise, random crashes might happen due to side effects. +;; +;; Destroyed Register values: +;; AF, BC, DE, HL, BC', DE', HL', IX +;; +;; Required memory: +;; C-bindings - 81 bytes +;; ASM-bindings - 67 bytes +;; +;; Time Measures: +;; (start code) +;; Case | microSecs (us) | CPU Cycles +;; ---------------------------------------------------------------- +;; | 29 + (6 + 33W)H | 116 + (24 + 132W)H +;; ---------------------------------------------------------------- +;; W=2,H=16 | 1181 | 4724 +;; W=4,H=32 | 4445 | 17780 +;; ---------------------------------------------------------------- +;; Asm saving | -16 | -64 +;; ---------------------------------------------------------------- +;; (end code) +;; W = *width* in bytes, H = *height* in bytes +;; +;; Credits: +;; Original routine optimized by @Docent and discussed in CPCWiki : +;; http://www.cpcwiki.eu/forum/programming/cpctelera-colorize-sprite/ +;; +;; Thanks to all of them for their help and support. +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +.globl dc_mode0_ct + +;; Macro to convert Pixel to xAxC xBxD format +.macro convertPixel + ;; From cpct_px2byteM0 + ld bc, #dc_mode0_ct ;; [3] BC points to conversion table (dc_mode0_ct) + + ;; Compute BC += A + add c ;; [1] | C += A + ld c, a ;; [1] | + sub a ;; [1] A = 0 (preserving Carry Flag) + adc b ;; [1] | B += Carry + ld b, a ;; [1] | + + ;; A = *(BC + A) + ld a, (bc) ;; [2] A = Value stored at the table pointed by BC +.endm + + ;; Convert newColor to pixel format (E) + ld a, h ;; [1] A = H new color index + convertPixel ;; [10] | Convert into A + ld e, a ;; [1] | E = A new color : xAxC xBxD + + ;; Convert oldColor to pixel format (D) + ld a, l ;; [1] A = L old color index + convertPixel ;; [10] | Convert into A + ld d, a ;; [1] | D = A old color : xAxC xBxD + + ld c, #0x55 ;; [2] C = Mask to get pixel A : xAxC xBxD + exx ;; [1] Switch to Alternate registers + + ld__ixl_c ;; [1] IXL = C (Width) + ld c, b ;; [1] C = B (Height) + +convertLoop: + ld__b_ixl ;; [2] B = IXL (Sprite Width) + +lineLoop: + ld a, (hl) ;; [2] A = (HL) current Byte of sprite + exx ;; [1] Switch to Default registers + + ld l, a ;; [1] L = A current Byte of sprite : ABAB ABAB + and c ;; [2] A |= C (C = 0x55) : xBxB xBxB + + cp d ;; [1] Test if pixel (A) is the old colour to be replaced (D) + jr nz, readPixelA ;; [2/3] If not equal go to next pixel + ld a, e ;; [1] else A = new colour to set (E) + +;; Pixel Mode 0 = ABAB ABAB +readPixelA: + ld h, a ;; [1] H = A (current colorized sprite) : xBxB xBxB + ld a, l ;; [1] L = A current Byte of sprite : ABAB ABAB + rrca ;; [1] A (current byte of sprite) >> 1 : ABAB ABAB -> xABA BABA + and c ;; [2] A |= Mask (0x55) : xAxA xAxA + + cp d ;; [1] Test if pixel (A) is the old colour to be replaced (D) + jr nz, readPixelB ;; [2/3] If not equal go to next pixel + ld a, e ;; [1] else A = new colour to set (E) + +readPixelB: + rlca ;; [1] A = xAxA xAxA << 1 : AxAx AxAx + or h ;; [1] A |= H (xBxB xBxB) : ABAB ABAB + +setByte: + exx ;; [1] Switch to Alternate registers + + ld (de), a ;; [2] Update current sprite byte with pixels + inc hl ;; [2] Next byte sprite source + inc de ;; [2] Next byte sprite colorized + djnz lineLoop ;; [3] Decrement B (Width) if != 0 goto lineLoop + +nextLine: + dec c ;; [1] Decrement C (Height) + jr nz, convertLoop ;; [2/3] If != O goto convertLoop + +end: + ;; Return is included in bindings + diff --git a/cpctelera/src/sprites/colorReplace/M0/cpct_spriteColorizeM0_asmbindings.s b/cpctelera/src/sprites/colorReplace/M0/cpct_spriteColorizeM0_asmbindings.s new file mode 100644 index 000000000..9ac97a5e6 --- /dev/null +++ b/cpctelera/src/sprites/colorReplace/M0/cpct_spriteColorizeM0_asmbindings.s @@ -0,0 +1,36 @@ +;;-----------------------------LICENSE NOTICE------------------------------------ +;; This file is part of CPCtelera: An Amstrad CPC Game Engine +;; Copyright (C) 2017 Arnaud Bouche (Arnaud6128) +;; Copyright (C) 2017 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) +;; +;; This program is free software: you can redistribute it and/or modify +;; it under the terms of the GNU Lesser General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU Lesser General Public License for more details. +;; +;; You should have received a copy of the GNU Lesser General Public License +;; along with this program. If not, see <http://www.gnu.org/licenses/>. +;;------------------------------------------------------------------------------- +.module cpct_sprites + +.include "../../../macros/cpct_undocumentedOpcodes.s" + +;; +;; ASM bindings for <cpct_spriteColorizeM0> +;; +cpct_spriteColorizeM0_asm:: ;; Assembly entry point + + ;; GET Parameters from the stack + ld (dms_restore_ix + 2), ix ;; [6] Save IX to restore it before returning + pop hl ;; [3] HL = Return Address + +.include /cpct_spriteColorizeM0.asm/ + +dms_restore_ix: + ld ix, #0000 ;; [4] Restore IX before returning + ret ;; [3] Return to caller \ No newline at end of file diff --git a/cpctelera/src/sprites/colorReplace/M0/cpct_spriteColorizeM0_cbindings.s b/cpctelera/src/sprites/colorReplace/M0/cpct_spriteColorizeM0_cbindings.s new file mode 100644 index 000000000..f31436707 --- /dev/null +++ b/cpctelera/src/sprites/colorReplace/M0/cpct_spriteColorizeM0_cbindings.s @@ -0,0 +1,48 @@ +;;-----------------------------LICENSE NOTICE------------------------------------ +;; This file is part of CPCtelera: An Amstrad CPC Game Engine +;; Copyright (C) 2017 Arnaud Bouche +;; Copyright (C) 2017 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) +;; +;; This program is free software: you can redistribute it and/or modify +;; it under the terms of the GNU Lesser General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU Lesser General Public License for more details. +;; +;; You should have received a copy of the GNU Lesser General Public License +;; along with this program. If not, see <http://www.gnu.org/licenses/>. +;;------------------------------------------------------------------------------- +.module cpct_sprites + +.include "../../../macros/cpct_undocumentedOpcodes.s" + +;; +;; C bindings for <cpct_spriteColorizeM0> +;; +;; 33 us, 14 bytes +;; +_cpct_spriteColorizeM0:: + + ;; GET Parameters from the stack + ld (dms_restore_ix + 2), ix ;; [6] Save IX to restore it before returning + pop hl ;; [3] HL = Return Address + + exx + pop hl ;; [3] HL' = Source address (Sprite) + pop de ;; [3] DE' = Destination Sprite color + pop bc ;; [5] BC' = (B = Sprite Height, C = Width) + exx + + ex (sp), hl ;; [6] HL = (H = newColor, L = oldColor) + ;; ... and leave Return Address at (SP) as we don't need to restore + ;; ... stack status because callin convention is __z88dk_callee + +.include /cpct_spriteColorizeM0.asm/ + +dms_restore_ix: + ld ix, #0000 ;; [4] Restore IX before returning + ret ;; [3] Return to caller \ No newline at end of file diff --git a/cpctelera/src/sprites/colorReplace/M0/cpct_spriteMaskedColorizeM0.asm b/cpctelera/src/sprites/colorReplace/M0/cpct_spriteMaskedColorizeM0.asm new file mode 100644 index 000000000..d6662e5c2 --- /dev/null +++ b/cpctelera/src/sprites/colorReplace/M0/cpct_spriteMaskedColorizeM0.asm @@ -0,0 +1,175 @@ +;;-----------------------------LICENSE NOTICE------------------------------------ +;; This file is part of CPCtelera: An Amstrad CPC Game Engine +;; Copyright (C) 2017 Arnaud Bouche (Arnaud6128) +;; Copyright (C) 2017 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) +;; +;; This program is free software: you can redistribute it and/or modify +;; it under the terms of the GNU Lesser General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU Lesser General Public License for more details. +;; +;; You should have received a copy of the GNU Lesser General Public License +;; along with this program. If not, see <http://www.gnu.org/licenses/>. +;;------------------------------------------------------------------------------- +.module cpct_sprites + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; +;; Function: cpct_spriteMaskedColorizeM0 +;; +;; Replace a color in a Masked sprite and copy to another or the same sprite. +;; +;; C Definition: +;; void <cpct_spriteMaskedColorizeM0> (void* *sprite*, void* *spriteColor*, <u8> *width*, <u8> *height*, <u8> *oldColor*, <u8> *newColor*) __z88dk_callee; +;; +;; Input Parameters (6 bytes): +;; (2B HL') sprite - Source Sprite Pointer (array of pixel data) +;; (2B DE') spriteColor - Destination Sprite Pointer (can be also the Source Sprite) (array of pixel data) +;; (1B C') height - Sprite Height in bytes (>0) +;; (1B B') width - Sprite Width in *bytes* (Beware, *not* in pixels!) +;; (1B L) oldColor - Color to replace +;; (1B H) newColor - New color +;; +;; Assembly call (Input parameters on registers): +;; > call cpct_spriteMaskedColorizeM0_asm +;; +;; Parameter Restrictions: +;; * *sprite* must be an array containing sprite's pixels data in screen pixel format +;; along with mask data. Each mask byte will contain enabled bits as those that should +;; be picked from the background (transparent) and disabled bits for those that will +;; be printed from sprite colour data. Each mask data byte must precede its associated +;; colour data byte. +;; Sprite must be rectangular and all bytes in the array must be consecutive pixels, +;; starting from top-left corner and going left-to-right, top-to-bottom down to the +;; bottom-right corner. Total amount of bytes in pixel array should be +;; 2 x *width* x *height* (mask data doubles array size). +;; * *spriteColor* must be an array containing the new sprite's pixels data with the new color. +;; Total amount of bytes in pixel array should be 2 x *width* x *height* (mask data doubles array size). +;; * *width* must be the width of the sprite *in bytes*. Always remember that the width must be +;; expressed in bytes and *not* in pixels. +;; The correspondence is mode 0 : 1 byte = 2 pixels +;; * *height* must be the height of the sprite in bytes, and must be greater than 0. +;; There is no practical upper limit to this value. Height of a sprite in +;; bytes and pixels is the same value, as bytes only group consecutive pixels in +;; the horizontal space. +;; * *oldColor* must be the index of color (0 to 15) to replace +;; * *newColor* must be the index of the new color (0 to 15) +;; +;; Known limitations: +;; * This function *will not work from ROM*, as it uses self-modifying code. +;; * This function requires the CPC firmware to be DISABLED. Otherwise, random crashes might happen due to side effects. +;; +;; Destroyed Register values: +;; AF, BC, DE, HL, BC', DE', HL', IX +;; +;; Required memory: +;; C-bindings - 87 bytes +;; ASM-bindings - 73 bytes +;; +;; Time Measures: +;; (start code) +;; Case | microSecs (us) | CPU Cycles +;; ---------------------------------------------------------------- +;; | 29 + (41 + 6W)H | 116 + (164 + 24W)H +;; ---------------------------------------------------------------- +;; W=2,H=16 | 2109 | 8436 +;; W=4,H=32 | 877 | 3508 +;; ---------------------------------------------------------------- +;; Asm saving | -16 | -64 +;; ---------------------------------------------------------------- +;; (end code) +;; W = *width* in bytes, H = *height* in bytes, HH = [(H-1)/8] +;; +;; Credits: +;; Original routine optimized by @Docent and discussed in CPCWiki : +;; http://www.cpcwiki.eu/forum/programming/cpctelera-colorize-sprite/ +;; +;; Thanks to all of them for their help and support. +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +.globl dc_mode0_ct + +;; Macro to convert Pixel to xAxC xBxD format +.macro convertPixel + ;; From cpct_px2byteM0 + ld bc, #dc_mode0_ct ;; [3] BC points to conversion table (dc_mode0_ct) + + ;; Compute BC += A + add c ;; [1] | C += A + ld c, a ;; [1] | + sub a ;; [1] A = 0 (preserving Carry Flag) + adc b ;; [1] | B += Carry + ld b, a ;; [1] | + + ;; A = *(BC + A) + ld a, (bc) ;; [2] A = Value stored at the table pointed by BC +.endm + + ;; Convert newColor to pixel format (E) + ld a, h ;; [1] A = H new color index + convertPixel ;; [10] | Convert into A + ld e, a ;; [1] | E = A new color : xAxC xBxD + + ;; Convert oldColor to pixel format (D) + ld a, l ;; [1] A = L old color index + convertPixel ;; [10] | Convert into A + ld d, a ;; [1] | D = A old color : xAxC xBxD + + ld c, #0x55 ;; [2] C = Mask to get pixel A : xAxC xBxD + exx ;; [1] Switch to Alternate registers + + ld__ixl_c ;; [1] IXL = C (Width) + ld c, b ;; [1] C = B (Height) + +convertLoop: + ld__b_ixl ;; [2] B = IXL (Sprite Width) + +lineLoop: + ld a, (hl) ;; [2] A = (HL) current Byte of sprite Mask + ld (de), a ;; [2] (DE) = A Copy of sprite Mask + inc hl ;; [2] Next byte sprite Color source + inc de ;; [2] Next byte sprite Color destination + ld a, (hl) ;; [2] A = (HL) current Byte of sprite Color + + exx ;; [1] Switch to Default registers + + ld l, a ;; [1] L = A current Byte of sprite : ABAB ABAB + and c ;; [2] A |= C (C = 0x55) : xBxB xBxB + + cp d ;; [1] Test if pixel (A) is the old colour to be replaced (D) + jr nz, readPixelA ;; [2/3] If not equal go to next pixel + ld a, e ;; [1] else A = new colour to set (E) + +;; Pixel Mode 0 = ABAB ABAB +readPixelA: + ld h, a ;; [1] H = A (current colorized sprite) : xBxB xBxB + ld a, l ;; [1] L = A current Byte of sprite : ABAB ABAB + rrca ;; [1] A (current byte of sprite) >> 1 : ABAB ABAB -> xABA BABA + and c ;; [2] A |= Mask (0x55) : xAxA xAxA + + cp d ;; [1] Test if pixel (A) is the old colour to be replaced (D) + jr nz, readPixelB ;; [2/3] If not equal go to next pixel + ld a, e ;; [1] else A = new colour to set (E) + +readPixelB: + rlca ;; [1] A = xAxA xAxA << 1 : AxAx AxAx + or h ;; [1] A |= H (xBxB xBxB) : ABAB ABAB + +setByte: + exx ;; [1] Switch to Alternate registers + + ld (de), a ;; [2] Update current sprite byte with pixels + inc hl ;; [2] Next byte sprite source + inc de ;; [2] Next byte sprite colorized + djnz lineLoop ;; [3] Decrement B (Width) if != 0 goto lineLoop + + dec c ;; [1] Decrement C (Height) + jr nz, convertLoop ;; [2/3] If C == O goto end + +end: + ;; Return is included in bindings \ No newline at end of file diff --git a/cpctelera/src/sprites/colorReplace/M0/cpct_spriteMaskedColorizeM0_asmbindings.s b/cpctelera/src/sprites/colorReplace/M0/cpct_spriteMaskedColorizeM0_asmbindings.s new file mode 100644 index 000000000..30440d708 --- /dev/null +++ b/cpctelera/src/sprites/colorReplace/M0/cpct_spriteMaskedColorizeM0_asmbindings.s @@ -0,0 +1,36 @@ +;;-----------------------------LICENSE NOTICE------------------------------------ +;; This file is part of CPCtelera: An Amstrad CPC Game Engine +;; Copyright (C) 2017 Arnaud Bouche (Arnaud6128) +;; Copyright (C) 2017 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) +;; +;; This program is free software: you can redistribute it and/or modify +;; it under the terms of the GNU Lesser General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU Lesser General Public License for more details. +;; +;; You should have received a copy of the GNU Lesser General Public License +;; along with this program. If not, see <http://www.gnu.org/licenses/>. +;;------------------------------------------------------------------------------- +.module cpct_sprites + +.include "../../../macros/cpct_undocumentedOpcodes.s" + +;; +;; ASM bindings for <cpct_spriteMaskedColorizeM0> +;; +cpct_spriteMaskedColorizeM0_asm:: ;; Assembly entry point + + ;; GET Parameters from the stack + ld (dms_restore_ix + 2), ix ;; [6] Save IX to restore it before returning + pop hl ;; [3] HL = Return Address + +.include /cpct_spriteMaskedColorizeM0.asm/ + +dms_restore_ix: + ld ix, #0000 ;; [4] Restore IX before returning + ret ;; [3] Return to caller \ No newline at end of file diff --git a/cpctelera/src/sprites/colorReplace/M0/cpct_spriteMaskedColorizeM0_cbindings.s b/cpctelera/src/sprites/colorReplace/M0/cpct_spriteMaskedColorizeM0_cbindings.s new file mode 100644 index 000000000..a2bba9de5 --- /dev/null +++ b/cpctelera/src/sprites/colorReplace/M0/cpct_spriteMaskedColorizeM0_cbindings.s @@ -0,0 +1,48 @@ +;;-----------------------------LICENSE NOTICE------------------------------------ +;; This file is part of CPCtelera: An Amstrad CPC Game Engine +;; Copyright (C) 2017 Arnaud Bouche (Arnaud6128) +;; Copyright (C) 2017 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) +;; +;; This program is free software: you can redistribute it and/or modify +;; it under the terms of the GNU Lesser General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU Lesser General Public License for more details. +;; +;; You should have received a copy of the GNU Lesser General Public License +;; along with this program. If not, see <http://www.gnu.org/licenses/>. +;;------------------------------------------------------------------------------- +.module cpct_sprites + +.include "../../../macros/cpct_undocumentedOpcodes.s" + +;; +;; C bindings for <cpct_spriteMaskedColorizeM0> +;; +;; 33 us, 14 bytes +;; +_cpct_spriteMaskedColorizeM0:: + + ;; GET Parameters from the stack + ld (dms_restore_ix + 2), ix ;; [6] Save IX to restore it before returning + pop hl ;; [3] HL = Return Address + + exx + pop hl ;; [3] HL' = Source address (Sprite) + pop de ;; [3] DE' = Destination Sprite color + pop bc ;; [5] BC' = (B = Sprite Height, C = Width) + exx + + ex (sp), hl ;; [6] HL = (H = newColor, L = oldColor) + ;; ... and leave Return Address at (SP) as we don't need to restore + ;; ... stack status because callin convention is __z88dk_callee + +.include /cpct_spriteMaskedColorizeM0.asm/ + +dms_restore_ix: + ld ix, #0000 ;; [4] Restore IX before returning + ret ;; [3] Return to caller \ No newline at end of file diff --git a/cpctelera/src/sprites/colorReplace/M1/cpct_drawSpriteColorizeM1.asm b/cpctelera/src/sprites/colorReplace/M1/cpct_drawSpriteColorizeM1.asm new file mode 100644 index 000000000..c6b6b8614 --- /dev/null +++ b/cpctelera/src/sprites/colorReplace/M1/cpct_drawSpriteColorizeM1.asm @@ -0,0 +1,228 @@ +;;-----------------------------LICENSE NOTICE------------------------------------ +;; This file is part of CPCtelera: An Amstrad CPC Game Engine +;; Copyright (C) 2017 Arnaud Bouche (Arnaud6128) +;; Copyright (C) 2017 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) +;; +;; This program is free software: you can redistribute it and/or modify +;; it under the terms of the GNU Lesser General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU Lesser General Public License for more details. +;; +;; You should have received a copy of the GNU Lesser General Public License +;; along with this program. If not, see <http://www.gnu.org/licenses/>. +;;------------------------------------------------------------------------------- +.module cpct_sprites + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; +;; Function: cpct_drawSpriteColorizeM1 +;; +;; Directly replace a color and draw a sprite to video memory. +;; +;; C Definition: +;; void <cpct_drawSpriteColorizeM1> (void* *sprite*, void* *memory*, <u8> *width*, <u8> *height*, <u8> *oldColor*, <u8> *newColor*) __z88dk_callee; +;; +;; Input Parameters (6 bytes): +;; (2B HL') sprite - Source Sprite Pointer (array of pixel data) +;; (2B DE') memory - Destination video memory pointer +;; (1B C' ) height - Sprite Height in bytes (>0) +;; (1B B' ) width - Sprite Width in *bytes* (Beware, *not* in pixels!) +;; (1B L ) oldColor - Color to replace +;; (1B H ) newColor - New color +;; +;; Assembly call (Input parameters on registers): +;; > call cpct_drawSpriteColorizeM1_asm +;; +;; Parameter Restrictions: +;; * *sprite* must be an array containing sprite's pixels data in screen pixel format. +;; Sprite must be rectangular and all bytes in the array must be consecutive pixels, +;; starting from top-left corner and going left-to-right, top-to-bottom down to the +;; bottom-right corner. Total amount of bytes in pixel array should be *width* x *height*. +;; * *memory* could be any place in memory, inside or outside current video memory. It +;; will be equally treated as video memory (taking into account CPC's video memory +;; disposition). This lets you copy sprites to software or hardware backbuffers, and +;; not only video memory. +;; * *width* must be the width of the sprite *in bytes*. Always remember that the width must be +;; expressed in bytes and *not* in pixels. +;; The correspondence is mode 1 : 1 byte = 4 pixels +;; * *height* must be the height of the sprite in bytes, and must be greater than 0. +;; There is no practical upper limit to this value. Height of a sprite in +;; bytes and pixels is the same value, as bytes only group consecutive pixels in +;; the horizontal space. +;; * *oldColor* must be the index of color (0 to 3) to replace +;; * *newColor* must be the index of the new color (0 to 3) +;; +;; Known limitations: +;; * This function does not do any kind of boundary check or clipping. If you +;; try to draw sprites on the frontier of your video memory or screen buffer +;; if might potentially overwrite memory locations beyond boundaries. This +;; could cause your program to behave erratically, hang or crash. Always +;; take the necessary steps to guarantee that you are drawing inside screen +;; or buffer boundaries. +;; * As this function receives a byte-pointer to memory, it can only +;; draw byte-sized and byte-aligned sprites. This means that the box cannot +;; start on non-byte aligned pixels (like odd-pixels, for instance) and +;; their sizes must be a multiple of a byte (2 in mode 0, 4 in mode 1 and +;; 8 in mode 2). +;; * This function *will not work from ROM*, as it uses self-modifying code. +;; * This function requires the CPC firmware to be DISABLED. Otherwise, random crashes might happen due to side effects. +;; +;; Destroyed Register values: +;; AF, BC, DE, HL, BC', DE', HL', IX +;; +;; Required memory: +;; C-bindings - 116 bytes +;; ASM-bindings - 103 bytes +;; +;; Time Measures: +;; (start code) +;; Case | microSecs (us) | CPU Cycles +;; ---------------------------------------------------------------- +;; | 29 + (36 + 61W)H | 116 + (144 + 244W)H +;; ---------------------------------------------------------------- +;; W=2,H=16 | 2557 | 10228 +;; W=4,H=32 | 8989 | 35956 +;; ---------------------------------------------------------------- +;; Asm saving | -16 | -64 +;; ---------------------------------------------------------------- +;; (end code) +;; W = *width* in bytes, H = *height* in bytes +;; +;; Credits: +;; Original routine optimized by @Docent and discussed in CPCWiki : +;; http://www.cpcwiki.eu/forum/programming/cpctelera-colorize-sprite/ +;; +;; Thanks to all of them for their help and support. +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +.globl dc_mode1_ct + +;; Macro to convert color to pixel Mode1 : Axxx Axxx +.macro convertPixel ;; From cpct_px2byteM1 + ld bc, #dc_mode1_ct ;; [3] BC points to conversion table (dc_mode1_ct) + + ;; Compute BC += A + add c ;; [1] | C += A + ld c, a ;; [1] | + sub a ;; [1] A = 0 (preserving Carry Flag) + adc b ;; [1] | B += Carry + ld b, a ;; [1] | + + ;; A = *(BC + A) + ld a, (bc) ;; [2] A = Value stored at the table pointed by BC +.endm + + ;; Convert newColor to pixel format (E) + ld a, h ;; [1] A = H new color index + convertPixel ;; [10] | Convert into A + ld e, a ;; [1] | E = A new color : Axxx Axxx + + ;; Convert oldColor to pixel format (D) + ld a, l ;; [1] A = L old color index + convertPixel ;; [10] | Convert into A + ld d, a ;; [1] | D = A old color : Axxx Axxx + + ld c, #0x88 ;; [2] C = Mask to get pixel A : Axxx Axxx + exx ;; [1] Switch to Alternate registers + + ld__ixl_c ;; [1] IXL = C (Width) + ld c, b ;; [1] C = B (Height) + +convertLoop: + ld (startLine), de ;; [6] Store DE start line (DestMem) + ld__b_ixl ;; [2] B = IXL (Sprite Width) + +lineLoop: + ld a, (hl) ;; [2] A = (HL) current Byte of sprite + exx ;; [1] Switch to Default registers + + ld l, a ;; [1] L = A current Byte of sprite : ABCD ABCD + and c ;; [2] A |= C (C = 0x88) : Axxx Axxx + + cp d ;; [1] Test if pixel (A) is the old colour to be replaced (D) + jr nz, readPixelA ;; [2/3] If not equal go to next pixel + ld a, e ;; [1] else A = new colour to set (E) + +readPixelA: + ld h, a ;; [1] H = A (current colorized sprite) : Axxx Axxx + + sla l ;; [2] L (current byte of sprite) << 1 : ABCD ABCD -> BCDx BCDx + ld a, l ;; [1] A = L : BCDx BCDx + and c ;; [2] A |= Mask (0x88) : Bxxx Bxxx + + cp d ;; [1] Test if pixel (A) is the old colour to be replaced (D) + jr nz, readPixelB ;; [2/3] If not equal go to next pixel + ld a, e ;; [1] else A = new colour to set (E) + +readPixelB: + rrca ;; [1] A = Axxx Axxx >> 1 : xBxx xBxx + or h ;; [1] A |= H (color byte) : Axxx Axxx + ld h, a ;; [1] H = A : ABxx ABxx + + sla l ;; [2] L ( BCDx BCDx) << 1 : CDxx CDxx + ld a, l ;; [1] A = L : CDxx CDxx + and c ;; [1] A |= C (C = 0x88) : Cxxx Cxxx + + cp d ;; [1] Test if pixel (A) is the old colour to be replaced (D) + jr nz, readPixelC ;; [2/3] If not equal go to next pixel + ld a, e ;; [1] else A = new colour to set (E) + +readPixelC: + rrca ;; [1] A = Axxx Axxx >> 1 : xBxx xBxx + rrca ;; [1] A = xxCx xxCx << 1 : xxCx xxCx + or h ;; [1] A |= H (ABxx ABxx) : ABCx ABCx + ld h, a ;; [1] H = A : ABCx ABCx + + sla l ;; [2] L (BCDx BCDx) << 1 : Dxxx Dxxx + ld a, l ;; [1] A = L : Dxxx Dxxx + and c ;; [1] A |= C (C = 0x88) : Dxxx Dxxx + + cp d ;; [1] Test if pixel (A) is the old colour to be replaced (D) + jr nz, readPixelD ;; [2/3] If not equal go to next pixel + ld a, e ;; [1] else A = new colour to set (E) + +readPixelD: + rrca ;; [1] A = Axxx Axxx >> 1 : xBxx xBxx + rrca ;; [1] A = xBxx xBxx >> 1 : xxCx xxCx + rrca ;; [1] A = xxCx xxxx >> 1 : xxxD xxxD + or h ;; [1] A |= H (ABCx ABCx) : ABCD ABCD + + exx ;; [1] Switch to Alternate registers + + ld (de), a ;; [2] Update current sprite byte with pixels + inc hl ;; [2] Next byte sprite source + inc de ;; [2] Next byte sprite colorized + djnz lineLoop ;; [3] Decrement B (Width) if B != 0 goto lineLoop + + dec c ;; [1] Decrement C (Height) + jr z, end ;; [2/3] If C == O goto end + +startLine = .+1 ;; Placeholder for the Start line adress + ld de, #0000 ;; [3] DE = Start Line + + ld a, d ;; [1] Start of next pixel line normally is 0x0800 bytes away. + add #0x08 ;; [2] so we add it to DE (just by adding 0x08 to D) + ld d, a ;; [1] + and #0x38 ;; [2] We check if we have crossed memory boundary (every 8 pixel lines).. + + jr nz, convertLoop ;; [2/3] .. by checking the 4 bits that identify present memory line. + ;; .... If 0, we have crossed boundaries + +dms_sprite_8bit_boundary_crossed: + ld a, e ;; [1] DE = DE + 0xC050h + add #0x50 ;; [2] -- Relocate DE pointer to the start of the next pixel line: + ld e, a ;; [1] -- DE is moved forward 3 memory banks plus 50 bytes (4000h * 3) + ld a, d ;; [1] -- which effectively is the same as moving it 1 bank backwards and then + adc #0xC0 ;; [2] -- 50 bytes forwards (which is what we want to move it to the next pixel line) + ld d, a ;; [1] -- Calculations are made with 8 bit maths as it is faster than other alternatives here + + jr convertLoop ;; [3] Jump to continue with next pixel line + +end: + ;; Return is included in bindings + diff --git a/cpctelera/src/sprites/colorReplace/M1/cpct_drawSpriteColorizeM1_asmbindings.s b/cpctelera/src/sprites/colorReplace/M1/cpct_drawSpriteColorizeM1_asmbindings.s new file mode 100644 index 000000000..44ca0f2b0 --- /dev/null +++ b/cpctelera/src/sprites/colorReplace/M1/cpct_drawSpriteColorizeM1_asmbindings.s @@ -0,0 +1,35 @@ +;;-----------------------------LICENSE NOTICE------------------------------------ +;; This file is part of CPCtelera: An Amstrad CPC Game Engine +;; Copyright (C) 2017 Arnaud Bouche (Arnaud6128) +;; Copyright (C) 2017 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) +;; +;; This program is free software: you can redistribute it and/or modify +;; it under the terms of the GNU Lesser General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU Lesser General Public License for more details. +;; +;; You should have received a copy of the GNU Lesser General Public License +;; along with this program. If not, see <http://www.gnu.org/licenses/>. +;;------------------------------------------------------------------------------- +.module cpct_sprites + +.include "../../../macros/cpct_undocumentedOpcodes.s" + +;; +;; ASM bindings for <cpct_drawSpriteColorizeM1> +;; +cpct_drawSpriteColorizeM1_asm:: ;; Assembly entry point + +;; GET Parameters from the stack +ld (dms_restore_ix + 2), ix ;; [6] Save IX to restore it before returning + +.include /cpct_drawSpriteColorizeM1.asm/ + +dms_restore_ix: + ld ix, #0000 ;; [4] Restore IX before returning + ret \ No newline at end of file diff --git a/cpctelera/src/sprites/colorReplace/M1/cpct_drawSpriteColorizeM1_cbindings.s b/cpctelera/src/sprites/colorReplace/M1/cpct_drawSpriteColorizeM1_cbindings.s new file mode 100644 index 000000000..22798d0f3 --- /dev/null +++ b/cpctelera/src/sprites/colorReplace/M1/cpct_drawSpriteColorizeM1_cbindings.s @@ -0,0 +1,48 @@ +;;-----------------------------LICENSE NOTICE------------------------------------ +;; This file is part of CPCtelera: An Amstrad CPC Game Engine +;; Copyright (C) 2017 Arnaud Bouche (Arnaud6128) +;; Copyright (C) 2017 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) +;; +;; This program is free software: you can redistribute it and/or modify +;; it under the terms of the GNU Lesser General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU Lesser General Public License for more details. +;; +;; You should have received a copy of the GNU Lesser General Public License +;; along with this program. If not, see <http://www.gnu.org/licenses/>. +;;------------------------------------------------------------------------------- +.module cpct_sprites + +.include "../../../macros/cpct_undocumentedOpcodes.s" + +;; +;; C bindings for <cpct_drawSpriteColorizeM1> +;; +;; 31 us, 13 bytes +;; +_cpct_drawSpriteColorizeM1:: + + ;; GET Parameters from the stack + ld (dms_restore_ix + 2), ix ;; [6] Save IX to restore it before returning + pop hl ;; [3] HL = Return Address + + exx + pop hl ;; [3] HL' = Source address (Sprite) + pop de ;; [3] DE' = Destination Memory + pop bc ;; [5] BC' = (B = Sprite Height, C = Width) + exx + + ex (sp), hl ;; [6] HL = (H = newColor, L = oldColor) + ;; ... and leave Return Address at (SP) as we don't need to restore + ;; ... stack status because callin convention is __z88dk_callee + +.include /cpct_drawSpriteColorizeM1.asm/ + +dms_restore_ix: + ld ix, #0000 ;; [4] Restore IX before returning + ret ;; [3] Return to caller \ No newline at end of file diff --git a/cpctelera/src/sprites/colorReplace/M1/cpct_drawSpriteMaskedAlignedColorizeM1.asm b/cpctelera/src/sprites/colorReplace/M1/cpct_drawSpriteMaskedAlignedColorizeM1.asm new file mode 100644 index 000000000..cbb50cdb3 --- /dev/null +++ b/cpctelera/src/sprites/colorReplace/M1/cpct_drawSpriteMaskedAlignedColorizeM1.asm @@ -0,0 +1,239 @@ +;;-----------------------------LICENSE NOTICE------------------------------------ +;; This file is part of CPCtelera: An Amstrad CPC Game Engine +;; Copyright (C) 2017 Arnaud Bouche (Arnaud6128) +;; Copyright (C) 2017 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) +;; +;; This program is free software: you can redistribute it and/or modify +;; it under the terms of the GNU Lesser General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU Lesser General Public License for more details. +;; +;; You should have received a copy of the GNU Lesser General Public License +;; along with this program. If not, see <http://www.gnu.org/licenses/>. +;;------------------------------------------------------------------------------- +.module cpct_sprites + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; +;; Function: cpct_drawSpriteMaskedAlignedColorizeM1 +;; +;; Directly replace a color and draw a sprite Masked Aligned to video memory. +;; +;; C Definition: +;; void <cpct_drawSpriteMaskedAlignedColorizeM1> (void* *sprite*, void* *memory*, <u8> *width*, <u8> *height*, +;; <u8> *oldColor*, <u8> *newColor*, <u8*> *pmasktable*) __z88dk_callee; +;; +;; Input Parameters (10 bytes): +;; (2B HL') sprite - Source Sprite Pointer (array of pixel data) +;; (2B DE') memory - Destination video memory pointer +;; (1B C' ) height - Sprite Height in bytes (>0) +;; (1B B' ) width - Sprite Width in *bytes* (Beware, *not* in pixels!) +;; (1B E ) oldColor - Color to replace +;; (1B D ) newColor - New color +;; (2B HL) pmasktable - Pointer to the aligned mask table used to create transparency +;; +;; Assembly call (Input parameters on registers): +;; > call cpct_drawSpriteMaskedAlignedColorizeM1_asm +;; +;; Parameter Restrictions: +;; * *sprite* must be an array containing sprite's pixels data in screen pixel format +;; Sprite must be rectangular and all bytes in the array must be consecutive pixels, +;; starting from top-left corner and going left-to-right, top-to-bottom down to the +;; bottom-right corner. Total amount of bytes in pixel array should be *width* x *height*. +;; * *memory* could be any place in memory, inside or outside current video memory. It +;; will be equally treated as video memory (taking into account CPC's video memory +;; disposition). This lets you copy sprites to software or hardware backbuffers, and +;; not only video memory. +;; * *width* must be the width of the sprite *in bytes*. Always remember that the width must be +;; expressed in bytes and *not* in pixels. +;; The correspondence is mode 0 : 1 byte = 4 pixels +;; * *height* must be the height of the sprite in bytes, and must be greater than 0. +;; There is no practical upper limit to this value. Height of a sprite in +;; bytes and pixels is the same value, as bytes only group consecutive pixels in +;; the horizontal space. +;; * *oldColor* must be the index of color (0 to 3) to replace +;; * *newColor* must be the index of the new color (0 to 3) +;; +;; Known limitations: +;; * This function does not do any kind of boundary check or clipping. If you +;; try to draw sprites on the frontier of your video memory or screen buffer +;; if might potentially overwrite memory locations beyond boundaries. This +;; could cause your program to behave erratically, hang or crash. Always +;; take the necessary steps to guarantee that you are drawing inside screen +;; or buffer boundaries. +;; * As this function receives a byte-pointer to memory, it can only +;; draw byte-sized and byte-aligned sprites. This means that the box cannot +;; start on non-byte aligned pixels (like odd-pixels, for instance) and +;; their sizes must be a multiple of a byte (2 in mode 0, 4 in mode 1 and +;; 8 in mode 2). +;; * This function *will not work from ROM*, as it uses self-modifying code. +;; * This function requires the CPC firmware to be DISABLED. Otherwise, random crashes might happen due to side effects. +;; +;; Destroyed Register values: +;; AF, BC, DE, HL, BC', DE', HL', IX +;; +;; Required memory: +;; C-bindings - 133 bytes +;; ASM-bindings - 117 bytes +;; +;; Time Measures: +;; (start code) +;; Case | microSecs (us) | CPU Cycles +;; ---------------------------------------------------------------- +;; | 32 + (33 + 75W)H | 128 + (132 + 300W)H +;; ---------------------------------------------------------------- +;; W=2,H=16 | 2960 | 11840 +;; W=4,H=32 | 10688 | 42752 +;; ---------------------------------------------------------------- +;; Asm saving | -16 | -64 +;; ---------------------------------------------------------------- +;; (end code) +;; W = *width* in bytes, H = *height* in bytes, HH = [(H-1)/8] +;; +;; Credits: +;; Original routine optimized by @Docent and discussed in CPCWiki : +;; http://www.cpcwiki.eu/forum/programming/cpctelera-colorize-sprite/ +;; +;; Thanks to all of them for their help and support. +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +.globl dc_mode1_ct + +;; Macro to convert color to pixel Mode1 : Axxx Axxx +.macro convertPixel ;; From cpct_px2byteM1 + ld bc, #dc_mode1_ct ;; [3] BC points to conversion table (dc_mode1_ct) + + ;; Compute BC += A + add c ;; [1] | C += A + ld c, a ;; [1] | + sub a ;; [1] A = 0 (preserving Carry Flag) + adc b ;; [1] | B += Carry + ld b, a ;; [1] | + + ;; A = *(BC + A) + ld a, (bc) ;; [2] A = Value stored at the table pointed by HL +.endm + + ;; Convert newColor to pixel format (E) + ld a, h ;; [1] A = H new color index + convertPixel ;; [10] | Convert into A + ld e, a ;; [1] | E = A new color : Axxx Axxx + + ;; Convert oldColor to pixel format (D) + ld a, l ;; [1] A = L old color index + convertPixel ;; [10] | Convert into A + ld d, a ;; [1] | D = A old color : Axxx Axxx + + ld c, #0x88 ;; [2] C = Mask to get pixel A : Axxx Axxx + exx ;; [1] Switch to Alternate registers + + ld__ixl_c ;; [1] IXL = C (Width) + ld c, b ;; [1] C = B (Height) + +convertLoop: + push de ;; [4] Store DE start line (DestMem) + ld__b_ixl ;; [2] B = IXL (Sprite Width) + +lineLoop: + ld a, (hl) ;; [2] A = (HL) current Byte of sprite Mask + exx ;; [1] Switch to Default registers + + ld l, a ;; [1] L = A current Byte of sprite : ABCD ABCD + and c ;; [2] A |= C (C = 0x88) : Axxx Axxx + + cp d ;; [1] Test if pixel (A) is the old colour to be replaced (D) + jr nz, readPixelA ;; [2/3] If not equal go to next pixel + ld a, e ;; [1] else A = new colour to set (E) + +readPixelA: + ld h, a ;; [1] H = A (current colorized sprite) : Axxx Axxx + + sla l ;; [2] L (current byte of sprite) << 1 : ABCD ABCD -> BCDx BCDx + ld a, l ;; [1] A = L : BCDx BCDx + and c ;; [2] A |= Mask (0x88) : Bxxx Bxxx + + cp d ;; [1] Test if pixel (A) is the old colour to be replaced (D) + jr nz, readPixelB ;; [2/3] If not equal go to next pixel + ld a, e ;; [1] else A = new colour to set (E) + +readPixelB: + rrca ;; [1] A = Axxx Axxx >> 1 : xBxx xBxx + or h ;; [1] A |= H (color byte) : Axxx Axxx + ld h, a ;; [1] H = A : ABxx ABxx + + sla l ;; [2] L ( BCDx BCDx) << 1 : CDxx CDxx + ld a, l ;; [1] A = L : CDxx CDxx + and c ;; [1] A |= C (C = 0x88) : Cxxx Cxxx + + cp d ;; [1] Test if pixel (A) is the old colour to be replaced (D) + jr nz, readPixelC ;; [2/3] If not equal go to next pixel + ld a, e ;; [1] else A = new colour to set (E) + +readPixelC: + rrca ;; [1] A = Axxx Axxx >> 1 : xBxx xBxx + rrca ;; [1] A = xxCx xxCx << 1 : xxCx xxCx + or h ;; [1] A |= H (ABxx ABxx) : ABCx ABCx + ld h, a ;; [1] H = A : ABCx ABCx + + sla l ;; [2] L (BCDx BCDx) << 1 : Dxxx Dxxx + ld a, l ;; [1] A = L : Dxxx Dxxx + and c ;; [1] A |= C (C = 0x88) : Dxxx Dxxx + + cp d ;; [1] Test if pixel (A) is the old colour to be replaced (D) + jr nz, readPixelD ;; [2/3] If not equal go to next pixel + ld a, e ;; [1] else A = new colour to set (E) + +readPixelD: + rrca ;; [1] A = Axxx Axxx >> 1 : xBxx xBxx + rrca ;; [1] A = xBxx xBxx >> 1 : xxCx xxCx + rrca ;; [1] A = xxCx xxxx >> 1 : xxxD xxxD + or h ;; [1] A |= H (ABCx ABCx) : ABCD ABCD + + exx ;; [1] Switch to Alternate registers + +drawByte: + push hl ;; [4] Store HL (current byte sprite source) + ld h, b ;; [1] H = B (Masked table adress High Byte) + ld l, a ;; [1] Access mask table element (table must be 256-byte aligned) + ld a, (de) ;; [2] Get the value of the byte of the screen where we are going to draw + and (hl) ;; [2] Erase background part that is to be overwritten (Mask step 1) + or l ;; [1] Add up background and sprite information in one byte (Mask step 2) + ld (de), a ;; [2] Save modified background + sprite data information into memory + pop hl ;; [3] Recover HL (current byte sprite source) + + inc hl ;; [2] Next byte sprite source + inc de ;; [2] Next byte sprite colorized + djnz lineLoop ;; [3] Decrement B (Width) if B != 0 goto lineLoop + + dec c ;; [1] Decrement C (Height) + jr z, end ;; [2/3] If C == O goto end + + pop de ;; [3] Restore DE start line (DestMem + + ld a, d ;; [1] Start of next pixel line normally is 0x0800 bytes away. + add #0x08 ;; [2] so we add it to DE (just by adding 0x08 to D) + ld d, a ;; [1] + and #0x38 ;; [2] We check if we have crossed memory boundary (every 8 pixel lines).. + + jr nz, convertLoop ;; [2/3] .. by checking the 4 bits that identify present memory line. + ;; .... If 0, we have crossed boundaries + +dms_sprite_8bit_boundary_crossed: + ld a, e ;; [1] DE = DE + 0xC050h + add #0x50 ;; [2] -- Relocate DE pointer to the start of the next pixel line: + ld e, a ;; [1] -- DE is moved forward 3 memory banks plus 50 bytes (4000h * 3) + ld a, d ;; [1] -- which effectively is the same as moving it 1 bank backwards and then + adc #0xC0 ;; [2] -- 50 bytes forwards (which is what we want to move it to the next pixel line) + ld d, a ;; [1] -- Calculations are made with 8 bit maths as it is faster than other alternatives here + + jr convertLoop ;; [3] Jump to continue with next pixel line + +end: + pop de ;; [3] Empty stack by getting last element (DestMem) + ;; Return is included in bindings + diff --git a/cpctelera/src/sprites/colorReplace/M1/cpct_drawSpriteMaskedAlignedColorizeM1_asmbindings.s b/cpctelera/src/sprites/colorReplace/M1/cpct_drawSpriteMaskedAlignedColorizeM1_asmbindings.s new file mode 100644 index 000000000..db02086d7 --- /dev/null +++ b/cpctelera/src/sprites/colorReplace/M1/cpct_drawSpriteMaskedAlignedColorizeM1_asmbindings.s @@ -0,0 +1,36 @@ +;;-----------------------------LICENSE NOTICE------------------------------------ +;; This file is part of CPCtelera: An Amstrad CPC Game Engine +;; Copyright (C) 2017 Arnaud Bouche (Arnaud6128) +;; Copyright (C) 2017 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) +;; +;; This program is free software: you can redistribute it and/or modify +;; it under the terms of the GNU Lesser General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU Lesser General Public License for more details. +;; +;; You should have received a copy of the GNU Lesser General Public License +;; along with this program. If not, see <http://www.gnu.org/licenses/>. +;;------------------------------------------------------------------------------- +.module cpct_sprites + +.include "../../../macros/cpct_undocumentedOpcodes.s" + +;; +;; ASM bindings for <cpct_drawSpriteMaskedAlignedColorizeM1> +;; +cpct_drawSpriteMaskedAlignedColorizeM1_asm:: ;; Assembly entry point + + ;; GET Parameters from the stack + ld (dms_restore_ix + 2), ix ;; [6] Save IX to restore it before returning + pop hl ;; [3] HL = Return Address + +.include /cpct_drawSpriteMaskedAlignedColorizeM1.asm/ + +dms_restore_ix: + ld ix, #0000 ;; [4] Restore IX before returning + ret ;; [3] Return to caller \ No newline at end of file diff --git a/cpctelera/src/sprites/colorReplace/M1/cpct_drawSpriteMaskedAlignedColorizeM1_cbindings.s b/cpctelera/src/sprites/colorReplace/M1/cpct_drawSpriteMaskedAlignedColorizeM1_cbindings.s new file mode 100644 index 000000000..f0b0a2130 --- /dev/null +++ b/cpctelera/src/sprites/colorReplace/M1/cpct_drawSpriteMaskedAlignedColorizeM1_cbindings.s @@ -0,0 +1,53 @@ +;;-----------------------------LICENSE NOTICE------------------------------------ +;; This file is part of CPCtelera: An Amstrad CPC Game Engine +;; Copyright (C) 2017 Arnaud Bouche (Arnaud6128) +;; Copyright (C) 2017 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) +;; +;; This program is free software: you can redistribute it and/or modify +;; it under the terms of the GNU Lesser General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU Lesser General Public License for more details. +;; +;; You should have received a copy of the GNU Lesser General Public License +;; along with this program. If not, see <http://www.gnu.org/licenses/>. +;;------------------------------------------------------------------------------- +.module cpct_sprites + +.include "../../../macros/cpct_undocumentedOpcodes.s" + +;; +;; C bindings for <cpct_drawSpriteMaskedAlignedColorizeM1> +;; +;; 39 us, 16 bytes +;; +_cpct_drawSpriteMaskedAlignedColorizeM1:: + + ;; GET Parameters from the stack + ld (dms_restore_ix + 2), ix ;; [6] Save IX to restore it before returning + pop hl ;; [3] HL = Return Address + + exx ;; [1] Switch to Alternate registers + pop hl ;; [3] HL' = Source address (Sprite) + pop de ;; [3] DE' = Destination Memory + pop bc ;; [5] BC' = (B = Sprite Height, C = Width) + + exx ;; [1] Switch to Default registers + pop de ;; [3] DE = (D = newColor, E = oldColor) + + ex (sp), hl ;; [6] HL = Table Mask address + ;; ... and leave Return Address at (SP) as we don't need to restore + ;; ... stack status because callin convention is __z88dk_callee + + ex de, hl ;; [1] HL <-> DE + + +.include /cpct_drawSpriteMaskedAlignedColorizeM1.asm/ + +dms_restore_ix: + ld ix, #0000 ;; [4] Restore IX before returning + ret ;; [3] Return to caller \ No newline at end of file diff --git a/cpctelera/src/sprites/colorReplace/M1/cpct_drawSpriteMaskedColorizeM1.asm b/cpctelera/src/sprites/colorReplace/M1/cpct_drawSpriteMaskedColorizeM1.asm new file mode 100644 index 000000000..9188f2ef3 --- /dev/null +++ b/cpctelera/src/sprites/colorReplace/M1/cpct_drawSpriteMaskedColorizeM1.asm @@ -0,0 +1,246 @@ +;;-----------------------------LICENSE NOTICE------------------------------------ +;; This file is part of CPCtelera: An Amstrad CPC Game Engine +;; Copyright (C) 2017 Arnaud Bouche (Arnaud6128) +;; Copyright (C) 2017 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) +;; +;; This program is free software: you can redistribute it and/or modify +;; it under the terms of the GNU Lesser General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU Lesser General Public License for more details. +;; +;; You should have received a copy of the GNU Lesser General Public License +;; along with this program. If not, see <http://www.gnu.org/licenses/>. +;;------------------------------------------------------------------------------- +.module cpct_sprites + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; +;; Function: cpct_drawSpriteMaskedColorizeM1 +;; +;; Directly replace a color and draw a sprite Masked to video memory. +;; +;; C Definition: +;; void <cpct_drawSpriteMaskedColorizeM1> (void* *sprite*, void* *memory*, <u8> *width*, <u8> *height*, <u8> *oldColor*, <u8> *newColor*) __z88dk_callee; +;; +;; Input Parameters (8 bytes): +;; (2B HL') sprite - Source Sprite Pointer (array of pixel data) +;; (2B DE') memory - Destination video memory pointer +;; (1B C' ) height - Sprite Height in bytes (>0) +;; (1B B' ) width - Sprite Width in *bytes* (Beware, *not* in pixels!) +;; (1B L ) oldColor - Color to replace +;; (1B H ) newColor - New color +;; +;; Assembly call (Input parameters on registers): +;; > call cpct_drawSpriteMaskedColorizeM1_asm +;; +;; Parameter Restrictions: +;; * *sprite* must be an array containing sprite's pixels data in screen pixel format +;; along with mask data. Each mask byte will contain enabled bits as those that should +;; be picked from the background (transparent) and disabled bits for those that will +;; be printed from sprite colour data. Each mask data byte must precede its associated +;; colour data byte. +;; Sprite must be rectangular and all bytes in the array must be consecutive pixels, +;; starting from top-left corner and going left-to-right, top-to-bottom down to the +;; bottom-right corner. Total amount of bytes in pixel array should be +;; 2 x *width* x *height* (mask data doubles array size). +;; * *memory* could be any place in memory, inside or outside current video memory. It +;; will be equally treated as video memory (taking into account CPC's video memory +;; disposition). This lets you copy sprites to software or hardware backbuffers, and +;; not only video memory. +;; * *width* must be the width of the sprite *in bytes*. Always remember that the width must be +;; expressed in bytes and *not* in pixels. +;; The correspondence is mode 0 : 1 byte = 4 pixels +;; * *height* must be the height of the sprite in bytes, and must be greater than 0. +;; There is no practical upper limit to this value. Height of a sprite in +;; bytes and pixels is the same value, as bytes only group consecutive pixels in +;; the horizontal space. +;; * *oldColor* must be the index of color (0 to 3) to replace +;; * *newColor* must be the index of the new color (0 to 3) +;; +;; Known limitations: +;; * This function does not do any kind of boundary check or clipping. If you +;; try to draw sprites on the frontier of your video memory or screen buffer +;; if might potentially overwrite memory locations beyond boundaries. This +;; could cause your program to behave erratically, hang or crash. Always +;; take the necessary steps to guarantee that you are drawing inside screen +;; or buffer boundaries. +;; * As this function receives a byte-pointer to memory, it can only +;; draw byte-sized and byte-aligned sprites. This means that the box cannot +;; start on non-byte aligned pixels (like odd-pixels, for instance) and +;; their sizes must be a multiple of a byte (2 in mode 0, 4 in mode 1 and +;; 8 in mode 2). +;; * This function *will not work from ROM*, as it uses self-modifying code. +;; * This function requires the CPC firmware to be DISABLED. Otherwise, random crashes might happen due to side effects. +;; +;; Destroyed Register values: +;; AF, BC, DE, HL, BC', DE', HL', IX +;; +;; Required memory: +;; C-bindings - 142 bytes +;; ASM-bindings - 129 bytes +;; +;; Time Measures: +;; (start code) +;; Case | microSecs (us) | CPU Cycles +;; ---------------------------------------------------------------- +;; | 29 + (36 + 93W)H | 116 + (144 + 372W)H +;; ---------------------------------------------------------------- +;; W=2,H=16 | 3581 | 14324 +;; W=4,H=32 | 13085 | 52340 +;; ---------------------------------------------------------------- +;; Asm saving | -16 | -64 +;; ---------------------------------------------------------------- +;; (end code) +;; W = *width* in bytes, H = *height* in bytes +;; +;; Credits: +;; Original routine optimized by @Docent and discussed in CPCWiki : +;; http://www.cpcwiki.eu/forum/programming/cpctelera-colorize-sprite/ +;; +;; Thanks to all of them for their help and support. +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +.globl dc_mode1_ct + +;; Macro to convert color to pixel Mode1 : Axxx Axxx +.macro convertPixel ;; From cpct_px2byteM1 + ld bc, #dc_mode1_ct ;; [3] BC points to conversion table (dc_mode1_ct) + + ;; Compute BC += A + add c ;; [1] | C += A + ld c, a ;; [1] | + sub a ;; [1] A = 0 (preserving Carry Flag) + adc b ;; [1] | B += Carry + ld b, a ;; [1] | + + ;; A = *(BC + A) + ld a, (bc) ;; [2] A = Value stored at the table pointed by BC +.endm + + ;; Convert newColor to pixel format (E) + ld a, h ;; [1] A = H new color index + convertPixel ;; [10] | Convert into A + ld e, a ;; [1] | E = A new color : Axxx Axxx + + ;; Convert oldColor to pixel format (D) + ld a, l ;; [1] A = L old color index + convertPixel ;; [10] | Convert into A + ld d, a ;; [1] | D = A old color : Axxx Axxx + + ld c, #0x88 ;; [2] C = First Mask to get pixel A : Axxx Axxx + exx ;; [1] Switch to Alternate registers + + ld__ixl_c ;; [1] IXL = C (Width) + ld c, b ;; [1] C = B (Height) + +convertLoop: + ld (startLine), de ;; [6] Store DE start line (DestMem) + ld__b_ixl ;; [2] B = IXL (Sprite Width) + +lineLoop: + inc hl ;; [2] Next byte sprite Color source + ld a, (hl) ;; [2] A = (HL) current Byte of sprite Color + dec hl ;; [2] Previous byte sprite Mask source + + exx ;; [1] Switch to Default registers + + ld l, a ;; [1] L = A current Byte of sprite : ABCD ABCD + + and c ;; [2] A |= C (C = 0x88) : Axxx Axxx + + cp d ;; [1] Test if pixel (A) is the old colour to be replaced (D) + jr nz, readPixelA ;; [2/3] If not equal go to next pixel + ld a, e ;; [1] else A = new colour to set (E) + +readPixelA: + ld h, a ;; [1] H = A (current colorized sprite) : Axxx Axxx + + sla l ;; [2] L (current byte of sprite) << 1 : ABCD ABCD -> BCDx BCDx + ld a, l ;; [1] A = L : BCDx BCDx + and c ;; [2] A |= Mask (0x88) : Bxxx Bxxx + + cp d ;; [1] Test if pixel (A) is the old colour to be replaced (D) + jr nz, readPixelB ;; [2/3] If not equal go to next pixel + ld a, e ;; [1] else A = new colour to set (E) + +readPixelB: + rrca ;; [1] A = Axxx Axxx >> 1 : xBxx xBxx + or h ;; [1] A |= H (color byte) : Axxx Axxx + ld h, a ;; [1] H = A : ABxx ABxx + + sla l ;; [2] L ( BCDx BCDx) << 1 : CDxx CDxx + ld a, l ;; [1] A = L : CDxx CDxx + and c ;; [1] A |= C (C = 0x88) : Cxxx Cxxx + + cp d ;; [1] Test if pixel (A) is the old colour to be replaced (D) + jr nz, readPixelC ;; [2/3] If not equal go to next pixel + ld a, e ;; [1] else A = new colour to set (E) + +readPixelC: + rrca ;; [1] A = Axxx Axxx >> 1 : xBxx xBxx + rrca ;; [1] A = xxCx xxCx << 1 : xxCx xxCx + or h ;; [1] A |= H (ABxx ABxx) : ABCx ABCx + ld h, a ;; [1] H = A : ABCx ABCx + + sla l ;; [2] L (BCDx BCDx) << 1 : Dxxx Dxxx + ld a, l ;; [1] A = L : Dxxx Dxxx + and c ;; [1] A |= C (C = 0x88) : Dxxx Dxxx + + cp d ;; [1] Test if pixel (A) is the old colour to be replaced (D) + jr nz, readPixelD ;; [2/3] If not equal go to next pixel + ld a, e ;; [1] else A = new colour to set (E) + +readPixelD: + rrca ;; [1] A = Axxx Axxx >> 1 : xBxx xBxx + rrca ;; [1] A = xBxx xBxx >> 1 : xxCx xxCx + rrca ;; [1] A = xxCx xxxx >> 1 : xxxD xxxD + or h ;; [1] A |= H (ABCx ABCx) : ABCD ABCD + + exx ;; [1] Switch to Alternate registers + +drawByte: + ld (sprite_color), a ;; [4] sprite_color = A (Sprite Byte) + + ld a, (de) ;; [2] Get next background byte into A + and (hl) ;; [2] Erase background part that is to be overwritten (Mask step 1) + inc hl ;; [3] HL += 1 => Point HL to Sprite Colour information +sprite_color = .+1 ;; Placeholder for the Sprite Color computed + or #00 ;; [2] Add up background and sprite information in one byte (Mask step 2) + ld (de), a ;; [2] Save modified background + sprite data information into memory + + inc hl ;; [2] Next byte sprite source + inc de ;; [2] Next byte Dest Memory + djnz lineLoop ;; [3] Decrement B (Width) if B != 0 goto lineLoop + + dec c ;; [1] Decrement C (Height) + jr z, end ;; [2/3] If C == O goto end + +startLine = .+1 ;; Placeholder for the Start line adress + ld de, #0000 ;; [3] DE = Start Line + + ld a, d ;; [1] Start of next pixel line normally is 0x0800 bytes away. + add #0x08 ;; [2] so we add it to DE (just by adding 0x08 to D) + ld d, a ;; [1] + and #0x38 ;; [2] We check if we have crossed memory boundary (every 8 pixel lines).. + + jr nz, convertLoop ;; [2/3] .. by checking the 4 bits that identify present memory line. + ;; .... If 0, we have crossed boundaries + +dms_sprite_8bit_boundary_crossed: + ld a, e ;; [1] DE = DE + 0xC050h + add #0x50 ;; [2] -- Relocate DE pointer to the start of the next pixel line: + ld e, a ;; [1] -- DE is moved forward 3 memory banks plus 50 bytes (4000h * 3) + ld a, d ;; [1] -- which effectively is the same as moving it 1 bank backwards and then + adc #0xC0 ;; [2] -- 50 bytes forwards (which is what we want to move it to the next pixel line) + ld d, a ;; [1] -- Calculations are made with 8 bit maths as it is faster than other alternatives here + + jr convertLoop ;; [3] Jump to continue with next pixel line + +end: + ;; Return is included in bindings + diff --git a/cpctelera/src/sprites/colorReplace/M1/cpct_drawSpriteMaskedColorizeM1_asmbindings.s b/cpctelera/src/sprites/colorReplace/M1/cpct_drawSpriteMaskedColorizeM1_asmbindings.s new file mode 100644 index 000000000..b2ed10933 --- /dev/null +++ b/cpctelera/src/sprites/colorReplace/M1/cpct_drawSpriteMaskedColorizeM1_asmbindings.s @@ -0,0 +1,36 @@ +;;-----------------------------LICENSE NOTICE------------------------------------ +;; This file is part of CPCtelera: An Amstrad CPC Game Engine +;; Copyright (C) 2017 Arnaud Bouche (Arnaud6128) +;; Copyright (C) 2017 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) +;; +;; This program is free software: you can redistribute it and/or modify +;; it under the terms of the GNU Lesser General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU Lesser General Public License for more details. +;; +;; You should have received a copy of the GNU Lesser General Public License +;; along with this program. If not, see <http://www.gnu.org/licenses/>. +;;------------------------------------------------------------------------------- +.module cpct_sprites + +.include "../../../macros/cpct_undocumentedOpcodes.s" + +;; +;; ASM bindings for <cpct_drawSpriteMaskedColorizeM1> +;; +cpct_drawSpriteMaskedColorizeM1_asm:: ;; Assembly entry point + + ;; GET Parameters from the stack + ld (dms_restore_ix + 2), ix ;; [6] Save IX to restore it before returning + pop hl ;; [3] HL = Return Address + +.include /cpct_drawSpriteMaskedColorizeM1.asm/ + +dms_restore_ix: + ld ix, #0000 ;; [4] Restore IX before returning + ret ;; [3] Return to caller \ No newline at end of file diff --git a/cpctelera/src/sprites/colorReplace/M1/cpct_drawSpriteMaskedColorizeM1_cbindings.s b/cpctelera/src/sprites/colorReplace/M1/cpct_drawSpriteMaskedColorizeM1_cbindings.s new file mode 100644 index 000000000..aa21c471c --- /dev/null +++ b/cpctelera/src/sprites/colorReplace/M1/cpct_drawSpriteMaskedColorizeM1_cbindings.s @@ -0,0 +1,48 @@ +;;-----------------------------LICENSE NOTICE------------------------------------ +;; This file is part of CPCtelera: An Amstrad CPC Game Engine +;; Copyright (C) 2017 Arnaud Bouche (Arnaud6128) +;; Copyright (C) 2017 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) +;; +;; This program is free software: you can redistribute it and/or modify +;; it under the terms of the GNU Lesser General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU Lesser General Public License for more details. +;; +;; You should have received a copy of the GNU Lesser General Public License +;; along with this program. If not, see <http://www.gnu.org/licenses/>. +;;------------------------------------------------------------------------------- +.module cpct_sprites + +.include "../../../macros/cpct_undocumentedOpcodes.s" + +;; +;; C bindings for <cpct_drawSpriteMaskedColorizeM1> +;; +;; 33 us, 13 bytes +;; +_cpct_drawSpriteMaskedColorizeM1:: + + ;; GET Parameters from the stack + ld (dms_restore_ix + 2), ix ;; [6] Save IX to restore it before returning + pop hl ;; [3] HL = Return Address + + exx + pop hl ;; [3] HL' = Source address (Sprite) + pop de ;; [3] DE' = Destination Memory + pop bc ;; [5] BC' = (B = Sprite Height, C = Width) + exx + + ex (sp), hl ;; [6] HL = (H = newColor, L = oldColor) + ;; ... and leave Return Address at (SP) as we don't need to restore + ;; ... stack status because callin convention is __z88dk_callee + +.include /cpct_drawSpriteMaskedColorizeM1.asm/ + +dms_restore_ix: + ld ix, #0000 ;; [4] Restore IX before returning + ret ;; [3] Return to caller \ No newline at end of file diff --git a/cpctelera/src/sprites/colorReplace/M1/cpct_spriteColorizeM1.asm b/cpctelera/src/sprites/colorReplace/M1/cpct_spriteColorizeM1.asm new file mode 100644 index 000000000..be64dd10b --- /dev/null +++ b/cpctelera/src/sprites/colorReplace/M1/cpct_spriteColorizeM1.asm @@ -0,0 +1,194 @@ +;;-----------------------------LICENSE NOTICE------------------------------------ +;; This file is part of CPCtelera: An Amstrad CPC Game Engine +;; Copyright (C) 2017 Arnaud Bouche (Arnaud6128) +;; Copyright (C) 2017 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) +;; +;; This program is free software: you can redistribute it and/or modify +;; it under the terms of the GNU Lesser General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU Lesser General Public License for more details. +;; +;; You should have received a copy of the GNU Lesser General Public License +;; along with this program. If not, see <http://www.gnu.org/licenses/>. +;;------------------------------------------------------------------------------- +.module cpct_sprites + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; +;; Function: cpct_spriteColorizeM1 +;; +;; Replace a color in a sprite and copy to another or the same sprite. +;; +;; C Definition: +;; void <cpct_spriteColorizeM1> (void* *sprite*, void* *spriteColor*, <u8> *width*, <u8> *height*, <u8> *oldColor*, <u8> *newColor*) __z88dk_callee; +;; +;; Input Parameters (6 bytes): +;; (2B HL') sprite - Source Sprite Pointer (array of pixel data) +;; (2B DE') spriteColor - Destination Sprite Pointer (can be also the Source Sprite) (array of pixel data) +;; (1B C' ) height - Sprite Height in bytes (>0) +;; (1B B' ) width - Sprite Width in *bytes* (Beware, *not* in pixels!) +;; (1B L ) oldColor - Color to replace +;; (1B H ) newColor - New color +;; +;; Assembly call (Input parameters on registers): +;; > call cpct_spriteColorizeM1_asm +;; +;; Parameter Restrictions: +;; * *sprite* must be an array containing sprite's pixels data in screen pixel format. +;; Sprite must be rectangular and all bytes in the array must be consecutive pixels, +;; starting from top-left corner and going left-to-right, top-to-bottom down to the +;; bottom-right corner. Total amount of bytes in pixel array should be *width* x *height*. +;; * *spriteColor* must be an array containing the new sprite's pixels data with the new color. +;; * *width* must be the width of the sprite *in bytes*. Always remember that the width must be +;; expressed in bytes and *not* in pixels. +;; The correspondence is mode 1 : 1 byte = 4 pixels +;; * *height* must be the height of the sprite in bytes, and must be greater than 0. +;; There is no practical upper limit to this value. Height of a sprite in +;; bytes and pixels is the same value, as bytes only group consecutive pixels in +;; the horizontal space. +;; * *oldColor* must be the index of color (0 to 3) to replace +;; * *newColor* must be the index of the new color (0 to 3) +;; +;; Known limitations: +;; * This function *will not work from ROM*, as it uses self-modifying code. +;; * This function requires the CPC firmware to be DISABLED. Otherwise, random crashes might happen due to side effects. +;; +;; Destroyed Register values: +;; AF, BC, DE, HL, BC', DE', HL', IX +;; +;; Required memory: +;; C-bindings - 73 bytes +;; ASM-bindings - 60 bytes +;; +;; Time Measures: +;; (start code) +;; Case | microSecs (us) | CPU Cycles +;; ---------------------------------------------------------------- +;; | 29 + (6 + 61W)H | 116 + (24 + 244W)H +;; ---------------------------------------------------------------- +;; W=2,H=16 | 2077 | 8308 +;; W=4,H=32 | 8029 | 32116 +;; ---------------------------------------------------------------- +;; Asm saving | -16 | -64 +;; ---------------------------------------------------------------- +;; (end code) +;; W = *width* in bytes, H = *height* in bytes +;; +;; Credits: +;; Original routine optimized by @Docent and discussed in CPCWiki : +;; http://www.cpcwiki.eu/forum/programming/cpctelera-colorize-sprite/ +;; +;; Thanks to all of them for their help and support. +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +.globl dc_mode1_ct + +;; Macro to convert color to pixel Mode1 : Axxx Axxx +.macro convertPixel ;; From cpct_px2byteM1 + ld bc, #dc_mode1_ct ;; [3] BC points to conversion table (dc_mode1_ct) + + ;; Compute HL += A + add c ;; [1] | C += A + ld c, a ;; [1] | + sub a ;; [1] A = 0 (preserving Carry Flag) + adc b ;; [1] | L += Carry + ld b, a ;; [1] | + + ;; A = *(BC + A) + ld a, (bc) ;; [2] A = Value stored at the table pointed by BC +.endm + + ;; Convert newColor to pixel format (E) + ld a, h ;; [1] A = H new color index + convertPixel ;; [10] | Convert into A + ld e, a ;; [1] | E = A new color : Axxx Axxx + + ;; Convert oldColor to pixel format (D) + ld a, l ;; [1] A = L old color index + convertPixel ;; [10] | Convert into A + ld d, a ;; [1] | D = A old color : Axxx Axxx + + ld c, #0x88 ;; [2] C = First Mask to get pixel A : Axxx Axxx + + exx ;; [1] Switch to Alternate registers + + ld__ixl_c ;; [1] IXL = C (Width) + ld c, b ;; [1] C = B (Height) + +convertLoop: + ld__b_ixl ;; [2] B = IXL (Sprite Width) + +lineLoop: + ld a, (hl) ;; [2] A = (HL) current Byte of sprite + exx ;; [1] Switch to Default registers + + ld l, a ;; [1] L = A current Byte of sprite : ABCD ABCD + and c ;; [2] A |= C (C = 0x88) : Axxx Axxx + + cp d ;; [1] Test if pixel (A) is the old colour to be replaced (D) + jr nz, readPixelA ;; [2/3] If not equal go to next pixel + ld a, e ;; [1] else A = new colour to set (E) + +readPixelA: + ld h, a ;; [1] H = A (current colorized sprite) : Axxx Axxx + + sla l ;; [2] L (current byte of sprite) << 1 : ABCD ABCD -> BCDx BCDx + ld a, l ;; [1] A = L : BCDx BCDx + and c ;; [2] A |= Mask (0x88) : Bxxx Bxxx + + cp d ;; [1] Test if pixel (A) is the old colour to be replaced (D) + jr nz, readPixelB ;; [2/3] If not equal go to next pixel + ld a, e ;; [1] else A = new colour to set (E) + +readPixelB: + rrca ;; [1] A = Axxx Axxx >> 1 : xBxx xBxx + or h ;; [1] A |= H (color byte) : Axxx Axxx + ld h, a ;; [1] H = A : ABxx ABxx + + sla l ;; [2] L ( BCDx BCDx) << 1 : CDxx CDxx + ld a, l ;; [1] A = L : CDxx CDxx + and c ;; [1] A |= C (C = 0x88) : Cxxx Cxxx + + cp d ;; [1] Test if pixel (A) is the old colour to be replaced (D) + jr nz, readPixelC ;; [2/3] If not equal go to next pixel + ld a, e ;; [1] else A = new colour to set (E) + +readPixelC: + rrca ;; [1] A = Axxx Axxx >> 1 : xBxx xBxx + rrca ;; [1] A = xxCx xxCx << 1 : xxCx xxCx + or h ;; [1] A |= H (ABxx ABxx) : ABCx ABCx + ld h, a ;; [1] H = A : ABCx ABCx + + sla l ;; [2] L (BCDx BCDx) << 1 : Dxxx Dxxx + ld a, l ;; [1] A = L : Dxxx Dxxx + and c ;; [1] A |= C (C = 0x88) : Dxxx Dxxx + + cp d ;; [1] Test if pixel (A) is the old colour to be replaced (D) + jr nz, readPixelD ;; [2/3] If not equal go to next pixel + ld a, e ;; [1] else A = new colour to set (E) + +readPixelD: + rrca ;; [1] A = Axxx Axxx >> 1 : xBxx xBxx + rrca ;; [1] A = xBxx xBxx >> 1 : xxCx xxCx + rrca ;; [1] A = xxCx xxxx >> 1 : xxxD xxxD + or h ;; [1] A |= H (ABCx ABCx) : ABCD ABCD + +setByte: + exx ;; [1] Switch to Alternate registers + + ld (de), a ;; [2] Update current sprite byte with pixels + inc hl ;; [2] Next byte sprite source + inc de ;; [2] Next byte sprite colorized + djnz lineLoop ;; [3] Decrement B (Width) if != 0 goto lineLoop + +nextLine: + dec c ;; [1] Decrement C (Height) + jr nz, convertLoop ;; [2/3] If != O goto convertLoop + +end: + ;; Return is included in bindings + diff --git a/cpctelera/src/sprites/colorReplace/M1/cpct_spriteColorizeM1_asmbindings.s b/cpctelera/src/sprites/colorReplace/M1/cpct_spriteColorizeM1_asmbindings.s new file mode 100644 index 000000000..4deb6e35b --- /dev/null +++ b/cpctelera/src/sprites/colorReplace/M1/cpct_spriteColorizeM1_asmbindings.s @@ -0,0 +1,35 @@ +;;-----------------------------LICENSE NOTICE------------------------------------ +;; This file is part of CPCtelera: An Amstrad CPC Game Engine +;; Copyright (C) 2017 Arnaud Bouche (Arnaud6128) +;; Copyright (C) 2017 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) +;; +;; This program is free software: you can redistribute it and/or modify +;; it under the terms of the GNU Lesser General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU Lesser General Public License for more details. +;; +;; You should have received a copy of the GNU Lesser General Public License +;; along with this program. If not, see <http://www.gnu.org/licenses/>. +;;------------------------------------------------------------------------------- +.module cpct_sprites + +.include "../../../macros/cpct_undocumentedOpcodes.s" + +;; +;; ASM bindings for <cpct_spriteColorizeM1> +;; +cpct_spriteColorizeM1_asm:: ;; Assembly entry point + + ;; GET Parameters from the stack + ld (dms_restore_ix + 2), ix ;; [6] Save IX to restore it before returning + +.include /cpct_spriteColorizeM1.asm/ + +dms_restore_ix: + ld ix, #0000 ;; [4] Restore IX before returning + ret ;; [3] Return to caller \ No newline at end of file diff --git a/cpctelera/src/sprites/colorReplace/M1/cpct_spriteColorizeM1_cbindings.s b/cpctelera/src/sprites/colorReplace/M1/cpct_spriteColorizeM1_cbindings.s new file mode 100644 index 000000000..8bca05567 --- /dev/null +++ b/cpctelera/src/sprites/colorReplace/M1/cpct_spriteColorizeM1_cbindings.s @@ -0,0 +1,48 @@ +;;-----------------------------LICENSE NOTICE------------------------------------ +;; This file is part of CPCtelera: An Amstrad CPC Game Engine +;; Copyright (C) 2017 Arnaud Bouche (Arnaud6128) +;; Copyright (C) 2017 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) +;; +;; This program is free software: you can redistribute it and/or modify +;; it under the terms of the GNU Lesser General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU Lesser General Public License for more details. +;; +;; You should have received a copy of the GNU Lesser General Public License +;; along with this program. If not, see <http://www.gnu.org/licenses/>. +;;------------------------------------------------------------------------------- +.module cpct_sprites + +.include "../../../macros/cpct_undocumentedOpcodes.s" + +;; +;; C bindings for <cpct_spriteColorizeM1> +;; +;; 33 us, 13 bytes +;; +_cpct_spriteColorizeM1:: + + ;; GET Parameters from the stack + ld (dms_restore_ix + 2), ix ;; [6] Save IX to restore it before returning + pop hl ;; [3] HL = Return Address + + exx + pop hl ;; [3] HL' = Source address (Sprite) + pop de ;; [3] DE' = Destination Sprite color + pop bc ;; [5] BC' = (B = Sprite Height, C = Width) + exx + + ex (sp), hl ;; [6] HL = (H = newColor, L = oldColor) + ;; ... and leave Return Address at (SP) as we don't need to restore + ;; ... stack status because callin convention is __z88dk_callee + +.include /cpct_spriteColorizeM1.asm/ + +dms_restore_ix: + ld ix, #0000 ;; [4] Restore IX before returning + ret ;; [3] Return to caller \ No newline at end of file diff --git a/cpctelera/src/sprites/colorReplace/M1/cpct_spriteMaskedColorizeM1.asm b/cpctelera/src/sprites/colorReplace/M1/cpct_spriteMaskedColorizeM1.asm new file mode 100644 index 000000000..c135f3fa7 --- /dev/null +++ b/cpctelera/src/sprites/colorReplace/M1/cpct_spriteMaskedColorizeM1.asm @@ -0,0 +1,205 @@ +;;-----------------------------LICENSE NOTICE------------------------------------ +;; This file is part of CPCtelera: An Amstrad CPC Game Engine +;; Copyright (C) 2017 Arnaud Bouche (Arnaud6128) +;; Copyright (C) 2017 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) +;; +;; This program is free software: you can redistribute it and/or modify +;; it under the terms of the GNU Lesser General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU Lesser General Public License for more details. +;; +;; You should have received a copy of the GNU Lesser General Public License +;; along with this program. If not, see <http://www.gnu.org/licenses/>. +;;------------------------------------------------------------------------------- +.module cpct_sprites +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; +;; Function: cpct_spriteMaskedColorizeM1 +;; +;; Replace a color in a Masked sprite and copy to another or the same sprite. +;; +;; C Definition: +;; void <cpct_spriteMaskedColorizeM1> (void* *sprite*, void* *spriteColor*, <u8> *width*, <u8> *height*, <u8> *oldColor*, <u8> *newColor*) __z88dk_callee; +;; +;; Input Parameters (6 bytes): +;; (2B HL') sprite - Source Sprite Pointer (array of pixel data) +;; (2B DE') spriteColor - Destination Sprite Pointer (can be also the Source Sprite) (array of pixel data) +;; (1B C') height - Sprite Height in bytes (>0) +;; (1B B') width - Sprite Width in *bytes* (Beware, *not* in pixels!) +;; (1B L) oldColor - Color to replace +;; (1B H) newColor - New color +;; +;; Assembly call (Input parameters on registers): +;; > call cpct_spriteMaskedColorizeM1_asm +;; +;; Parameter Restrictions: +;; * *sprite* must be an array containing sprite's pixels data in screen pixel format +;; along with mask data. Each mask byte will contain enabled bits as those that should +;; be picked from the background (transparent) and disabled bits for those that will +;; be printed from sprite colour data. Each mask data byte must precede its associated +;; colour data byte. +;; Sprite must be rectangular and all bytes in the array must be consecutive pixels, +;; starting from top-left corner and going left-to-right, top-to-bottom down to the +;; bottom-right corner. Total amount of bytes in pixel array should be +;; 2 x *width* x *height* (mask data doubles array size). +;; * *spriteColor* must be an array containing the new sprite's pixels data with the new color. +;; Total amount of bytes in pixel array should be 2 x *width* x *height* (mask data doubles array size). +;; * *width* must be the width of the sprite *in bytes*. Always remember that the width must be +;; expressed in bytes and *not* in pixels. +;; The correspondence is mode 1 : 1 byte = 4 pixels +;; * *height* must be the height of the sprite in bytes, and must be greater than 0. +;; There is no practical upper limit to this value. Height of a sprite in +;; bytes and pixels is the same value, as bytes only group consecutive pixels in +;; the horizontal space. +;; * *oldColor* must be the index of color (0 to 3) to replace +;; * *newColor* must be the index of the new color (0 to 3) +;; +;; Known limitations: +;; * This function *will not work from ROM*, as it uses self-modifying code. +;; * This function requires the CPC firmware to be DISABLED. Otherwise, random crashes might happen due to side effects. +;; +;; Destroyed Register values: +;; AF, BC, DE, HL, BC', DE', HL', IX +;; +;; Required memory: +;; C-bindings - 110 bytes +;; ASM-bindings - 97 bytes +;; +;; Time Measures: +;; (start code) +;; Case | microSecs (us) | CPU Cycles +;; ---------------------------------------------------------------- +;; | 29 + (6 + 71W)H | 116 + (24 + 284W)H +;; ---------------------------------------------------------------- +;; W=2,H=16 | 2397 | 9588 +;; W=4,H=32 | 9309 | 37236 +;; ---------------------------------------------------------------- +;; Asm saving | -16 | -64 +;; ---------------------------------------------------------------- +;; (end code) +;; W = *width* in bytes, H = *height* in bytes +;; +;; Credits: +;; Original routine optimized by @Docent and discussed in CPCWiki : +;; http://www.cpcwiki.eu/forum/programming/cpctelera-colorize-sprite/ +;; +;; Thanks to all of them for their help and support. +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +.globl dc_mode1_ct + +;; Macro to convert color to pixel Mode1 : Axxx Axxx +.macro convertPixel ;; From cpct_px2byteM1 + ld bc, #dc_mode1_ct ;; [3] HL points to conversion table (dc_mode1_ct) + + ;; Compute HL += A + add c ;; [1] | L += A + ld c, a ;; [1] | + sub a ;; [1] A = 0 (preserving Carry Flag) + adc b ;; [1] | H += Carry + ld b, a ;; [1] | + + ;; A = *(HL + A) + ld a, (bc) ;; [2] A = Value stored at the table pointed by HL +.endm + + ;; Convert newColor to pixel format (E) + ld a, h ;; [1] A = H new color index + convertPixel ;; [10] | Convert into A + ld e, a ;; [1] | E = A new color : Axxx Axxx + + ;; Convert oldColor to pixel format (D) + ld a, l ;; [1] A = L old color index + convertPixel ;; [10] | Convert into A + ld d, a ;; [1] | D = A old color : Axxx Axxx + + ld c, #0x88 ;; [2] C = First Mask to get pixel A : Axxx Axxx + + exx ;; [1] Switch to Alternate registers + + ld__ixl_c ;; [1] IXL = C (Width) + ld c, b ;; [1] C = B (Height) + +convertLoop: + ld__b_ixl ;; [2] B = IXL (Sprite Width) + +lineLoop: + ld a, (hl) ;; [2] A = (HL) current Byte of sprite Mask + ld (de), a ;; [2] (DE) = A Copy of sprite Mask + inc hl ;; [2] Next byte sprite Color source + inc de ;; [2] Next byte sprite Color destination + ld a, (hl) ;; [2] A = (HL) current Byte of sprite Color + + exx ;; [1] Switch to Default registers + + ld l, a ;; [1] L = A current Byte of sprite : ABCD ABCD + + and c ;; [2] A |= C (C = 0x88) : Axxx Axxx + + cp d ;; [1] Test if pixel (A) is the old colour to be replaced (D) + jr nz, readPixelA ;; [2/3] If not equal go to next pixel + ld a, e ;; [1] else A = new colour to set (E) + +readPixelA: + ld h, a ;; [1] H = A (current colorized sprite) : Axxx Axxx + + sla l ;; [2] L (current byte of sprite) << 1 : ABCD ABCD -> BCDx BCDx + ld a, l ;; [1] A = L : BCDx BCDx + and c ;; [2] A |= Mask (0x88) : Bxxx Bxxx + + cp d ;; [1] Test if pixel (A) is the old colour to be replaced (D) + jr nz, readPixelB ;; [2/3] If not equal go to next pixel + ld a, e ;; [1] else A = new colour to set (E) + +readPixelB: + rrca ;; [1] A = Axxx Axxx >> 1 : xBxx xBxx + or h ;; [1] A |= H (color byte) : Axxx Axxx + ld h, a ;; [1] H = A : ABxx ABxx + + sla l ;; [2] L ( BCDx BCDx) << 1 : CDxx CDxx + ld a, l ;; [1] A = L : CDxx CDxx + and c ;; [1] A |= C (C = 0x88) : Cxxx Cxxx + + cp d ;; [1] Test if pixel (A) is the old colour to be replaced (D) + jr nz, readPixelC ;; [2/3] If not equal go to next pixel + ld a, e ;; [1] else A = new colour to set (E) + +readPixelC: + rrca ;; [1] A = Axxx Axxx >> 1 : xBxx xBxx + rrca ;; [1] A = xxCx xxCx << 1 : xxCx xxCx + or h ;; [1] A |= H (ABxx ABxx) : ABCx ABCx + ld h, a ;; [1] H = A : ABCx ABCx + + sla l ;; [2] L (BCDx BCDx) << 1 : Dxxx Dxxx + ld a, l ;; [1] A = L : Dxxx Dxxx + and c ;; [1] A |= C (C = 0x88) : Dxxx Dxxx + + cp d ;; [1] Test if pixel (A) is the old colour to be replaced (D) + jr nz, readPixelD ;; [2/3] If not equal go to next pixel + ld a, e ;; [1] else A = new colour to set (E) + +readPixelD: + rrca ;; [1] A = Axxx Axxx >> 1 : xBxx xBxx + rrca ;; [1] A = xBxx xBxx >> 1 : xxCx xxCx + rrca ;; [1] A = xxCx xxxx >> 1 : xxxD xxxD + or h ;; [1] A |= H (ABCx ABCx) : ABCD ABCD + +setByte: + exx ;; [1] Switch to Alternate registers + + ld (de), a ;; [2] Update current sprite byte with pixels + inc hl ;; [2] Next byte sprite source + inc de ;; [2] Next byte sprite colorized + djnz lineLoop ;; [3] Decrement B (Width) if != 0 goto lineLoop + +nextLine: + dec c ;; [1] Decrement C (Height) + jr nz, convertLoop ;; [2/3] If != O goto convertLoop + +end: + ;; Return is included in bindings \ No newline at end of file diff --git a/cpctelera/src/sprites/colorReplace/M1/cpct_spriteMaskedColorizeM1_asmbindings.s b/cpctelera/src/sprites/colorReplace/M1/cpct_spriteMaskedColorizeM1_asmbindings.s new file mode 100644 index 000000000..cc7d49e23 --- /dev/null +++ b/cpctelera/src/sprites/colorReplace/M1/cpct_spriteMaskedColorizeM1_asmbindings.s @@ -0,0 +1,36 @@ +;;-----------------------------LICENSE NOTICE------------------------------------ +;; This file is part of CPCtelera: An Amstrad CPC Game Engine +;; Copyright (C) 2017 Arnaud Bouche (Arnaud6128) +;; Copyright (C) 2017 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) +;; +;; This program is free software: you can redistribute it and/or modify +;; it under the terms of the GNU Lesser General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU Lesser General Public License for more details. +;; +;; You should have received a copy of the GNU Lesser General Public License +;; along with this program. If not, see <http://www.gnu.org/licenses/>. +;;------------------------------------------------------------------------------- +.module cpct_sprites + +.include "../../../macros/cpct_undocumentedOpcodes.s" + +;; +;; ASM bindings for <cpct_spriteMaskedColorizeM1> +;; +cpct_spriteMaskedColorizeM1_asm:: ;; Assembly entry point + + ;; GET Parameters from the stack + ld (dms_restore_ix + 2), ix ;; [6] Save IX to restore it before returning + pop hl ;; [3] HL = Return Address + +.include /cpct_spriteMaskedColorizeM1.asm/ + +dms_restore_ix: + ld ix, #0000 ;; [4] Restore IX before returning + ret ;; [3] Return to caller \ No newline at end of file diff --git a/cpctelera/src/sprites/colorReplace/M1/cpct_spriteMaskedColorizeM1_cbindings.s b/cpctelera/src/sprites/colorReplace/M1/cpct_spriteMaskedColorizeM1_cbindings.s new file mode 100644 index 000000000..3e4784f8a --- /dev/null +++ b/cpctelera/src/sprites/colorReplace/M1/cpct_spriteMaskedColorizeM1_cbindings.s @@ -0,0 +1,48 @@ +;;-----------------------------LICENSE NOTICE------------------------------------ +;; This file is part of CPCtelera: An Amstrad CPC Game Engine +;; Copyright (C) 2017 Arnaud Bouche (Arnaud6128) +;; Copyright (C) 2017 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) +;; +;; This program is free software: you can redistribute it and/or modify +;; it under the terms of the GNU Lesser General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU Lesser General Public License for more details. +;; +;; You should have received a copy of the GNU Lesser General Public License +;; along with this program. If not, see <http://www.gnu.org/licenses/>. +;;------------------------------------------------------------------------------- +.module cpct_sprites + +.include "../../../macros/cpct_undocumentedOpcodes.s" + +;; +;; C bindings for <cpct_spriteMaskedColorizeM1> +;; +;; 33 us, 13 bytes +;; +_cpct_spriteMaskedColorizeM1:: + + ;; GET Parameters from the stack + ld (dms_restore_ix + 2), ix ;; [6] Save IX to restore it before returning + pop hl ;; [3] HL = Return Address + + exx + pop hl ;; [3] HL' = Source address (Sprite) + pop de ;; [3] DE' = Destination Sprite color + pop bc ;; [5] BC' = (B = Sprite Height, C = Width) + exx + + ex (sp), hl ;; [6] HL = (H = newColor, L = oldColor) + ;; ... and leave Return Address at (SP) as we don't need to restore + ;; ... stack status because callin convention is __z88dk_callee + +.include /cpct_spriteMaskedColorizeM1.asm/ + +dms_restore_ix: + ld ix, #0000 ;; [4] Restore IX before returning + ret ;; [3] Return to caller \ No newline at end of file From d0ff60a4735a7cac6970528890addc2e90b2a0ca Mon Sep 17 00:00:00 2001 From: Arnaud <arnaud_bouche@hotmail.com> Date: Fri, 19 Jan 2018 21:22:59 +0100 Subject: [PATCH 03/31] Add header to replaceColor functions and update Sprites.h --- .../src/sprites/colorReplace/colorReplace.h | 49 +++++++++++++++++++ cpctelera/src/sprites/sprites.h | 1 + 2 files changed, 50 insertions(+) create mode 100644 cpctelera/src/sprites/colorReplace/colorReplace.h diff --git a/cpctelera/src/sprites/colorReplace/colorReplace.h b/cpctelera/src/sprites/colorReplace/colorReplace.h new file mode 100644 index 000000000..598498fdc --- /dev/null +++ b/cpctelera/src/sprites/colorReplace/colorReplace.h @@ -0,0 +1,49 @@ +//-----------------------------LICENSE NOTICE------------------------------------ +// This file is part of CPCtelera: An Amstrad CPC Game Engine +// Copyright (C) 2018 Arnaud Bouche (Arnaud6128) +// Copyright (C) 2018 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +//------------------------------------------------------------------------------- + +//##################################################################### +//### MODULE: Sprites +//### SUBMODULE: ColorReplace +//##################################################################### +//### This module contains routines to replace colors in sprites +//##################################################################### +// + +#ifndef CPCT_COLORREPLACE_H +#define CPCT_COLORREPLACE_H + +// Functions to replace a color in sprite M0 +void cpct_spriteColorizeM0(u8* sprite, u8* spriteColor, u8 width, u8 height, u8 oldColor, u8 newColor) __z88dk_callee; +void cpct_spriteMaskedColorizeM0(u8* sprite, u8* spriteColor, u8 width, u8 height, u8 oldColor, u8 newColor) __z88dk_callee; + +// Functions to draw a sprite M0 with a color replaced +void cpct_drawSpriteColorizeM0(u8* sprite, u8* destMem, u8 width, u8 height, u8 oldColor, u8 newColor) __z88dk_callee; +void cpct_drawSpriteMaskedColorizeM0(u8* sprite, u8* destMem, u8 width, u8 height, u8 oldColor, u8 newColor) __z88dk_callee; +void cpct_drawSpriteMaskedAlignedColorizeM0(u8* sprite, u8* destMem, u8 width, u8 height, u8 oldColor, u8 newColor, const u8* maskTable) __z88dk_callee; + +// Functions to replace a color in sprite M1 +void cpct_spriteColorizeM1(u8* sprite, u8* spriteColor, u8 width, u8 height, u8 oldColor, u8 newColor) __z88dk_callee; +void cpct_spriteMaskedColorizeM1(u8* sprite, u8* spriteColor, u8 width, u8 height, u8 oldColor, u8 newColor) __z88dk_callee; + +// Functions to draw a sprite M1 with a color replaced +void cpct_drawSpriteColorizeM1(u8* sprite, u8* destMem, u8 width, u8 height, u8 oldColor, u8 newColor) __z88dk_callee; +void cpct_drawSpriteMaskedColorizeM1(u8* sprite, u8* destMem, u8 width, u8 height, u8 oldColor, u8 newColor) __z88dk_callee; +void cpct_drawSpriteMaskedAlignedColorizeM1(u8* sprite, u8* destMem, u8 width, u8 height, u8 oldColor, u8 newColor, const u8* maskTable) __z88dk_callee; + +#endif \ No newline at end of file diff --git a/cpctelera/src/sprites/sprites.h b/cpctelera/src/sprites/sprites.h index 45e3ec054..51855ea57 100644 --- a/cpctelera/src/sprites/sprites.h +++ b/cpctelera/src/sprites/sprites.h @@ -34,6 +34,7 @@ #include "drawTile/drawTile.h" #include "flipping/flipping.h" #include "blending/blending.h" +#include "colorReplace/colorReplace.h" // Functions to transform firmware colours for a group of pixels into a byte in screen pixel format extern u8 cpct_px2byteM0 (u8 px0, u8 px1) __z88dk_callee; From 61de6da2bcee7d0d34dd3e55c68b4e7501e4a2e5 Mon Sep 17 00:00:00 2001 From: Arnaud <arnaud_bouche@hotmail.com> Date: Fri, 19 Jan 2018 21:26:46 +0100 Subject: [PATCH 04/31] Add sprite color replace in M0 example --- examples/medium/colorReplace/Makefile | 38 ++ .../medium/colorReplace/cfg/build_config.mk | 161 ++++++++ .../colorReplace/cfg/image_conversion.mk | 74 ++++ examples/medium/colorReplace/img/baloon.png | Bin 0 -> 322 bytes .../medium/colorReplace/img/circle_trans.png | Bin 0 -> 113 bytes examples/medium/colorReplace/img/cloud.png | Bin 0 -> 524 bytes examples/medium/colorReplace/img/roof.png | Bin 0 -> 366 bytes examples/medium/colorReplace/img/square.png | Bin 0 -> 103 bytes .../medium/colorReplace/img/star_trans.png | Bin 0 -> 107 bytes .../src/asm/macros/cpct_reverseBits.s | 263 +++++++++++++ .../src/asm/macros/cpct_undocumentedOpcodes.s | 97 +++++ .../M0/cpct_drawSpriteColorizeM0.asm | 203 ++++++++++ .../cpct_drawSpriteColorizeM0_asmbindings.s | 36 ++ .../M0/cpct_drawSpriteColorizeM0_cbindings.s | 48 +++ ...cpct_drawSpriteMaskedAlignedColorizeM0.asm | 215 ++++++++++ ...priteMaskedAlignedColorizeM0_asmbindings.s | 36 ++ ...wSpriteMaskedAlignedColorizeM0_cbindings.s | 52 +++ .../M0/cpct_drawSpriteMaskedColorizeM0.asm | 216 ++++++++++ ...t_drawSpriteMaskedColorizeM0_asmbindings.s | 36 ++ ...pct_drawSpriteMaskedColorizeM0_cbindings.s | 48 +++ .../colorReplace/M0/cpct_spriteColorizeM0.asm | 166 ++++++++ .../M0/cpct_spriteColorizeM0_asmbindings.s | 36 ++ .../M0/cpct_spriteColorizeM0_cbindings.s | 48 +++ .../M0/cpct_spriteMaskedColorizeM0.asm | 175 +++++++++ .../cpct_spriteMaskedColorizeM0_asmbindings.s | 36 ++ .../cpct_spriteMaskedColorizeM0_cbindings.s | 48 +++ .../M1/cpct_drawSpriteColorizeM1.asm | 228 +++++++++++ .../cpct_drawSpriteColorizeM1_asmbindings.s | 35 ++ .../M1/cpct_drawSpriteColorizeM1_cbindings.s | 48 +++ ...cpct_drawSpriteMaskedAlignedColorizeM1.asm | 239 +++++++++++ ...priteMaskedAlignedColorizeM1_asmbindings.s | 36 ++ ...wSpriteMaskedAlignedColorizeM1_cbindings.s | 53 +++ .../M1/cpct_drawSpriteMaskedColorizeM1.asm | 246 ++++++++++++ ...t_drawSpriteMaskedColorizeM1_asmbindings.s | 36 ++ ...pct_drawSpriteMaskedColorizeM1_cbindings.s | 48 +++ .../colorReplace/M1/cpct_spriteColorizeM1.asm | 194 +++++++++ .../M1/cpct_spriteColorizeM1_asmbindings.s | 35 ++ .../M1/cpct_spriteColorizeM1_cbindings.s | 48 +++ .../M1/cpct_spriteMaskedColorizeM1.asm | 205 ++++++++++ .../cpct_spriteMaskedColorizeM1_asmbindings.s | 36 ++ .../cpct_spriteMaskedColorizeM1_cbindings.s | 48 +++ .../medium/colorReplace/src/declarations.h | 90 +++++ examples/medium/colorReplace/src/drawing.c | 371 ++++++++++++++++++ examples/medium/colorReplace/src/drawing.h | 31 ++ examples/medium/colorReplace/src/main.c | 69 ++++ .../medium/colorReplace/src/manageVideoMem.c | 88 +++++ .../medium/colorReplace/src/manageVideoMem.h | 47 +++ .../medium/colorReplace/src/sprites/baloon.c | 43 ++ .../medium/colorReplace/src/sprites/baloon.h | 12 + .../colorReplace/src/sprites/circle_trans.c | 12 + .../colorReplace/src/sprites/circle_trans.h | 10 + .../medium/colorReplace/src/sprites/cloud.c | 60 +++ .../medium/colorReplace/src/sprites/cloud.h | 10 + .../medium/colorReplace/src/sprites/roof.c | 26 ++ .../medium/colorReplace/src/sprites/roof.h | 10 + .../medium/colorReplace/src/sprites/square.c | 12 + .../medium/colorReplace/src/sprites/square.h | 10 + .../colorReplace/src/sprites/star_trans.c | 12 + .../colorReplace/src/sprites/star_trans.h | 10 + 59 files changed, 4490 insertions(+) create mode 100644 examples/medium/colorReplace/Makefile create mode 100644 examples/medium/colorReplace/cfg/build_config.mk create mode 100644 examples/medium/colorReplace/cfg/image_conversion.mk create mode 100644 examples/medium/colorReplace/img/baloon.png create mode 100644 examples/medium/colorReplace/img/circle_trans.png create mode 100644 examples/medium/colorReplace/img/cloud.png create mode 100644 examples/medium/colorReplace/img/roof.png create mode 100644 examples/medium/colorReplace/img/square.png create mode 100644 examples/medium/colorReplace/img/star_trans.png create mode 100644 examples/medium/colorReplace/src/asm/macros/cpct_reverseBits.s create mode 100644 examples/medium/colorReplace/src/asm/macros/cpct_undocumentedOpcodes.s create mode 100644 examples/medium/colorReplace/src/asm/sprites/colorReplace/M0/cpct_drawSpriteColorizeM0.asm create mode 100644 examples/medium/colorReplace/src/asm/sprites/colorReplace/M0/cpct_drawSpriteColorizeM0_asmbindings.s create mode 100644 examples/medium/colorReplace/src/asm/sprites/colorReplace/M0/cpct_drawSpriteColorizeM0_cbindings.s create mode 100644 examples/medium/colorReplace/src/asm/sprites/colorReplace/M0/cpct_drawSpriteMaskedAlignedColorizeM0.asm create mode 100644 examples/medium/colorReplace/src/asm/sprites/colorReplace/M0/cpct_drawSpriteMaskedAlignedColorizeM0_asmbindings.s create mode 100644 examples/medium/colorReplace/src/asm/sprites/colorReplace/M0/cpct_drawSpriteMaskedAlignedColorizeM0_cbindings.s create mode 100644 examples/medium/colorReplace/src/asm/sprites/colorReplace/M0/cpct_drawSpriteMaskedColorizeM0.asm create mode 100644 examples/medium/colorReplace/src/asm/sprites/colorReplace/M0/cpct_drawSpriteMaskedColorizeM0_asmbindings.s create mode 100644 examples/medium/colorReplace/src/asm/sprites/colorReplace/M0/cpct_drawSpriteMaskedColorizeM0_cbindings.s create mode 100644 examples/medium/colorReplace/src/asm/sprites/colorReplace/M0/cpct_spriteColorizeM0.asm create mode 100644 examples/medium/colorReplace/src/asm/sprites/colorReplace/M0/cpct_spriteColorizeM0_asmbindings.s create mode 100644 examples/medium/colorReplace/src/asm/sprites/colorReplace/M0/cpct_spriteColorizeM0_cbindings.s create mode 100644 examples/medium/colorReplace/src/asm/sprites/colorReplace/M0/cpct_spriteMaskedColorizeM0.asm create mode 100644 examples/medium/colorReplace/src/asm/sprites/colorReplace/M0/cpct_spriteMaskedColorizeM0_asmbindings.s create mode 100644 examples/medium/colorReplace/src/asm/sprites/colorReplace/M0/cpct_spriteMaskedColorizeM0_cbindings.s create mode 100644 examples/medium/colorReplace/src/asm/sprites/colorReplace/M1/cpct_drawSpriteColorizeM1.asm create mode 100644 examples/medium/colorReplace/src/asm/sprites/colorReplace/M1/cpct_drawSpriteColorizeM1_asmbindings.s create mode 100644 examples/medium/colorReplace/src/asm/sprites/colorReplace/M1/cpct_drawSpriteColorizeM1_cbindings.s create mode 100644 examples/medium/colorReplace/src/asm/sprites/colorReplace/M1/cpct_drawSpriteMaskedAlignedColorizeM1.asm create mode 100644 examples/medium/colorReplace/src/asm/sprites/colorReplace/M1/cpct_drawSpriteMaskedAlignedColorizeM1_asmbindings.s create mode 100644 examples/medium/colorReplace/src/asm/sprites/colorReplace/M1/cpct_drawSpriteMaskedAlignedColorizeM1_cbindings.s create mode 100644 examples/medium/colorReplace/src/asm/sprites/colorReplace/M1/cpct_drawSpriteMaskedColorizeM1.asm create mode 100644 examples/medium/colorReplace/src/asm/sprites/colorReplace/M1/cpct_drawSpriteMaskedColorizeM1_asmbindings.s create mode 100644 examples/medium/colorReplace/src/asm/sprites/colorReplace/M1/cpct_drawSpriteMaskedColorizeM1_cbindings.s create mode 100644 examples/medium/colorReplace/src/asm/sprites/colorReplace/M1/cpct_spriteColorizeM1.asm create mode 100644 examples/medium/colorReplace/src/asm/sprites/colorReplace/M1/cpct_spriteColorizeM1_asmbindings.s create mode 100644 examples/medium/colorReplace/src/asm/sprites/colorReplace/M1/cpct_spriteColorizeM1_cbindings.s create mode 100644 examples/medium/colorReplace/src/asm/sprites/colorReplace/M1/cpct_spriteMaskedColorizeM1.asm create mode 100644 examples/medium/colorReplace/src/asm/sprites/colorReplace/M1/cpct_spriteMaskedColorizeM1_asmbindings.s create mode 100644 examples/medium/colorReplace/src/asm/sprites/colorReplace/M1/cpct_spriteMaskedColorizeM1_cbindings.s create mode 100644 examples/medium/colorReplace/src/declarations.h create mode 100644 examples/medium/colorReplace/src/drawing.c create mode 100644 examples/medium/colorReplace/src/drawing.h create mode 100644 examples/medium/colorReplace/src/main.c create mode 100644 examples/medium/colorReplace/src/manageVideoMem.c create mode 100644 examples/medium/colorReplace/src/manageVideoMem.h create mode 100644 examples/medium/colorReplace/src/sprites/baloon.c create mode 100644 examples/medium/colorReplace/src/sprites/baloon.h create mode 100644 examples/medium/colorReplace/src/sprites/circle_trans.c create mode 100644 examples/medium/colorReplace/src/sprites/circle_trans.h create mode 100644 examples/medium/colorReplace/src/sprites/cloud.c create mode 100644 examples/medium/colorReplace/src/sprites/cloud.h create mode 100644 examples/medium/colorReplace/src/sprites/roof.c create mode 100644 examples/medium/colorReplace/src/sprites/roof.h create mode 100644 examples/medium/colorReplace/src/sprites/square.c create mode 100644 examples/medium/colorReplace/src/sprites/square.h create mode 100644 examples/medium/colorReplace/src/sprites/star_trans.c create mode 100644 examples/medium/colorReplace/src/sprites/star_trans.h diff --git a/examples/medium/colorReplace/Makefile b/examples/medium/colorReplace/Makefile new file mode 100644 index 000000000..184f61b39 --- /dev/null +++ b/examples/medium/colorReplace/Makefile @@ -0,0 +1,38 @@ +##-----------------------------LICENSE NOTICE------------------------------------ +## This file is part of CPCtelera: An Amstrad CPC Game Engine +## Copyright (C) 2015 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) +## +## This program is free software: you can redistribute it and/or modify +## it under the terms of the GNU Lesser General Public License as published by +## the Free Software Foundation, either version 3 of the License, or +## (at your option) any later version. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU Lesser General Public License for more details. +## +## You should have received a copy of the GNU Lesser General Public License +## along with this program. If not, see <http://www.gnu.org/licenses/>. +##------------------------------------------------------------------------------ + +########################################################################### +## CPCTELERA ENGINE ## +## Main Building Makefile for Projects ## +##-----------------------------------------------------------------------## +## This file contains the rules for building a CPCTelera project. These ## +## These rules work generically for every CPCTelera project. ## +## Usually, this file should be left unchanged: ## +## * Project's build configuration is to be found in build_config.mk ## +## * Global paths and tool configuration is located at $(CPCT_PATH)/cfg/## +########################################################################### + +## +## PROJECT CONFIGURATION (you may change things there to setup this project) +## +include cfg/build_config.mk + +## +## USE GLOBAL MAKEFILE (general rules for building CPCtelera projects) +## +include $(CPCT_PATH)/cfg/global_main_makefile.mk diff --git a/examples/medium/colorReplace/cfg/build_config.mk b/examples/medium/colorReplace/cfg/build_config.mk new file mode 100644 index 000000000..9a25a157e --- /dev/null +++ b/examples/medium/colorReplace/cfg/build_config.mk @@ -0,0 +1,161 @@ +##-----------------------------LICENSE NOTICE------------------------------------ +## This file is part of CPCtelera: An Amstrad CPC Game Engine +## Copyright (C) 2015 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) +## +## This program is free software: you can redistribute it and/or modify +## it under the terms of the GNU Lesser General Public License as published by +## the Free Software Foundation, either version 3 of the License, or +## (at your option) any later version. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU Lesser General Public License for more details. +## +## You should have received a copy of the GNU Lesser General Public License +## along with this program. If not, see <http://www.gnu.org/licenses/>. +##------------------------------------------------------------------------------ + +########################################################################### +## CPCTELERA ENGINE ## +## Build configuration file ## +##-----------------------------------------------------------------------## +## This file is intendend for you to be able to config the way in which ## +## you would like to build this example of use of the CPCtelera Engine. ## +## Below you will find several configuration sections with the macros ## +## available to configure the build, along with explanation comments to ## +## help you understand what they do. Please, change everything you want. ## +########################################################################### + +## CPCTELERA MAIN PATH +## Sets CPCTelera main path for accessing tools and configuration. This +## variable must point to the folder where source and tools are contained. +## Setup creates and environment variable that will be generally used. +## However, when environment variable is not available, this variable +## should have the correct value for the project to compile. +## If you change folder structure, CPCT_PATH should reflect this change. +## This variable should always have the absolute path value. +## +#>> Uses environment variable $(CPCT_PATH) + +#### +## SECTION 1: Project configuration +## +## This section establishes source and object subfolders and the binary objects to +## be built. Normally, you want to change the OBJ files you want to be built, selecting +## only the ones that contain the actual code that will be used by you in your application. +##### + +# Name of the project (without spaces, as it will be used as filename) +# and Z80 memory location where code will start in the generated binary +PROJNAME := color +Z80CODELOC := 0x40 + +## +## Folders +## +## SRCDIR = Source files for the project +## DSKFILESDIR = Input files to be added to the final DSK production +## OBJDIR = Object files generated on compilation +## +SRCDIR := src +DSKFILESDIR := dsk_files +OBJDIR := obj + +## +## File extensions +## +## C_EXT = C source files that will be automatically compiled +## ASM_EXT = ASM source files that will be automatically compiled +## BIN_EXT = Binary files that will be automatically converted to C source files for compilation +## OBJ_EXT = Object files generated after compilation +## DSKINC_EXT = Flag object files generated after file inclusion into DSK (to signal that a file has been included) +## +C_EXT := c +ASM_EXT := s +BIN_EXT := bin +OBJ_EXT := rel +DSKINC_EXT := dskinc + +## +## Output Binaries Configuration +## +## IHXFILE = Binary file that SDCC produces after compilation and linkage +## BINFILE = Binary file that is finally included in DSK and CDT (produced by Hex2Bin) +## CDT = CDT file produced +## DSK = DSK file produced +## DSKINC = Flag object file produced to signal DSK already has all include files in it +## +IHXFILE := $(OBJDIR)/$(PROJNAME).ihx +BINFILE := $(OBJDIR)/$(PROJNAME).bin +CDT := $(PROJNAME).cdt +DSK := $(PROJNAME).dsk +DSKINC := $(OBJDIR)/$(DSK).$(DSKINC_EXT) + +## +## TARGETs generated by Makefile: remove those you don't want to be generated +## +## $(CDT): Generates the CDT file with main binary +## $(DSK): Generates the DSK file with main binary +## $(DSKINC): Includes all files from DSKFILESDIR into DSK as binaries +## +TARGET := $(CDT) $(DSK) $(DSKINC) + +## +## OBJS2CLEAN: Additional objects to be removed when running "make clean" +## +OBJS2CLEAN := + +#### +## SECTION 2: TOOL PATH CONFIGURATION +## +## Paths are configured in the global_paths.mk configuration file included +## here. You may overwrite the values of path variables after the include +## if you wanted specific configuration for this project. +#### +include $(CPCT_PATH)/cfg/global_paths.mk + +#### +## SECTION 3: COMPILATION CONFIGURATION +## +## Flags used to configure the compilation of your code. They are usually +## fine for most of the projects, but you may change them for special uses. +##### +Z80CCFLAGS := +Z80ASMFLAGS := -l -o -s +Z80CCINCLUDE := -I$(CPCT_SRC) +Z80CCLINKARGS := -mz80 --no-std-crt0 -Wl-u \ + --code-loc $(Z80CODELOC) \ + --data-loc 0 -l$(CPCT_LIB) +#### +## SECTION 4: CALCULATED FOLDERS, SUBFOLDERS AND FILES +## +## These macros calculate code subfolders, get all the source files and generate +## the corresponding subfolders and files in the object directory. All subfolders +## and files with source extension found are added, up to 1 level of depth in +## folder structure inside the main source directory. +#### +include $(CPCT_PATH)/cfg/global_functions.mk + +# Convert images and tilemaps +include cfg/image_conversion.mk + +# Calculate all subdirectories +SUBDIRS := $(filter-out ., $(shell find $(SRCDIR) -type d -print)) +OBJDSKINCSDIR := $(OBJDIR)/$(DSKFILESDIR) +OBJSUBDIRS := $(OBJDSKINCSDIR) $(foreach DIR, $(SUBDIRS), $(patsubst $(SRCDIR)%, $(OBJDIR)%, $(DIR))) + +# Calculate all source files +CFILES := $(foreach DIR, $(SUBDIRS), $(wildcard $(DIR)/*.$(C_EXT))) +CFILES := $(IMGCFILES) $(filter-out $(IMGCFILES), $(CFILES)) +ASMFILES := $(foreach DIR, $(SUBDIRS), $(wildcard $(DIR)/*.$(ASM_EXT))) +BIN2CFILES := $(foreach DIR, $(SUBDIRS), $(wildcard $(DIR)/*.$(BIN_EXT))) +DSKINCSRCFILES := $(wildcard $(DSKFILESDIR)/*) + +# Calculate all object files +BIN_OBJFILES := $(patsubst %.$(BIN_EXT), %.$(C_EXT), $(BIN2CFILES)) +CFILES := $(filter-out $(BIN_OBJFILES), $(CFILES)) +C_OBJFILES := $(patsubst $(SRCDIR)%, $(OBJDIR)%, $(patsubst %.$(C_EXT), %.$(OBJ_EXT), $(BIN_OBJFILES) $(CFILES))) +ASM_OBJFILES := $(patsubst $(SRCDIR)%, $(OBJDIR)%, $(patsubst %.$(ASM_EXT), %.$(OBJ_EXT), $(ASMFILES))) +DSKINCOBJFILES := $(foreach FILE, $(DSKINCSRCFILES), $(patsubst $(DSKFILESDIR)/%, $(OBJDSKINCSDIR)/%, $(FILE)).$(DSKINC_EXT)) +OBJFILES := $(C_OBJFILES) $(ASM_OBJFILES) diff --git a/examples/medium/colorReplace/cfg/image_conversion.mk b/examples/medium/colorReplace/cfg/image_conversion.mk new file mode 100644 index 000000000..185e4dbab --- /dev/null +++ b/examples/medium/colorReplace/cfg/image_conversion.mk @@ -0,0 +1,74 @@ +##-----------------------------LICENSE NOTICE------------------------------------ +## This file is part of CPCtelera: An Amstrad CPC Game Engine +## Copyright (C) 2016 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) +## +## This program is free software: you can redistribute it and/or modify +## it under the terms of the GNU Lesser General Public License as published by +## the Free Software Foundation, either version 3 of the License, or +## (at your option) any later version. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU Lesser General Public License for more details. +## +## You should have received a copy of the GNU Lesser General Public License +## along with this program. If not, see <http://www.gnu.org/licenses/>. +##------------------------------------------------------------------------------ + +############################################################################ +## CPCTELERA ENGINE ## +## Automatic image conversion file ## +##------------------------------------------------------------------------## +## This file is intended for users to automate image conversion from JPG, ## +## PNG, GIF, etc. into C-arrays. ## +## ## +## Macro used for conversion is IMG2SPRITES, which has up to 9 parameters:## +## (1): Image file to be converted into C sprite (PNG, JPG, GIF, etc) ## +## (2): Graphics mode (0,1,2) for the generated C sprite ## +## (3): Prefix to add to all C-identifiers generated ## +## (4): Width in pixels of each sprite/tile/etc that will be generated ## +## (5): Height in pixels of each sprite/tile/etc that will be generated ## +## (6): Firmware palette used to convert the image file into C values ## +## (7): (mask / tileset /) ## +## - "mask": generate interlaced mask for all sprites converted ## +## - "tileset": generate a tileset array with pointers to all sprites ## +## (8): Output subfolder for generated .C/.H files (in project folder) ## +## (9): (hwpalette) ## +## - "hwpalette": output palette array with hardware colour values ## +## (10): Aditional options (you can use this to pass aditional modifiers ## +## to cpct_img2tileset) ## +## ## +## Macro is used in this way (one line for each image to be converted): ## +## $(eval $(call IMG2SPRITES,(1),(2),(3),(4),(5),(6),(7),(8),(9), (10))) ## +## ## +## Important: ## +## * Do NOT separate macro parameters with spaces, blanks or other chars.## +## ANY character you put into a macro parameter will be passed to the ## +## macro. Therefore ...,src/sprites,... will represent "src/sprites" ## +## folder, whereas ..., src/sprites,... means " src/sprites" folder. ## +## ## +## * You can omit parameters but leaving them empty. Therefore, if you ## +## wanted to specify an output folder but do not want your sprites to ## +## have mask and/or tileset, you may omit parameter (7) leaving it empty ## +## $(eval $(call IMG2SPRITES,imgs/1.png,0,g,4,8,$(PAL),,src/)) ## +############################################################################ + +## Example firmware palette definition as variable in cpct_img2tileset format + +PALETTE={13 1 2 3 6 4 5 8 17 9 18 15 24 0 11 26} + +## Example image conversion +## This example would convert img/example.png into src/example.{c|h} files. +## A C-array called pre_example[24*12*2] would be generated with the definition +## of the image example.png in mode 0 screen pixel format, with interlaced mask. +## The palette used for conversion is given through the PALETTE variable and +## a pre_palette[16] array will be generated with the 16 palette colours as +## hardware colour values. + +$(eval $(call IMG2SPRITES,img/baloon.png,0,g,0,0,$(PALETTE),,src/sprites,hwpalette)) +$(eval $(call IMG2SPRITES,img/square.png,0,g,0,0,$(PALETTE),,src/sprites,)) +$(eval $(call IMG2SPRITES,img/star_trans.png,0,g,0,0,$(PALETTE),mask,src/sprites,)) +$(eval $(call IMG2SPRITES,img/circle_trans.png,0,g,0,0,$(PALETTE),mask,src/sprites,)) +$(eval $(call IMG2SPRITES,img/roof.png,0,g,0,0,$(PALETTE),,src/sprites,)) +$(eval $(call IMG2SPRITES,img/cloud.png,0,g,0,0,$(PALETTE),,src/sprites,)) \ No newline at end of file diff --git a/examples/medium/colorReplace/img/baloon.png b/examples/medium/colorReplace/img/baloon.png new file mode 100644 index 0000000000000000000000000000000000000000..04314b1fa2383936f00529e805ec13fc483dceaa GIT binary patch literal 322 zcmV-I0lof-P)<h;3K|Lk000e1NJLTq000yK001Hg0ssI3r_Ww|00009a7bBm000tn z000tn0p4aGcmMzZ^hrcPRCwCuRqYalAPD5qd2_mwaQP7HX71NHPLsI{xPTEe6VZ5n zhFsI$uJ3X_CoW=<a_uQZU`{xgb!%ms3-hP$L=-&MVrvZI*_xbx^vC*g9}(8(7HuJ1 zQc&~gIiN<IFq4+WQECG-@>|@o0m3qj(@6M&dxVO3Sz=I8mJ-pOTci0_vfpoSB5$`h zvg}2*>a>KeGR8h(KD)w;gx=M{A?4oIEQ(s92zGS_eNy#|J2Ez;qHVN%2^UsGx6B7s zx|{Tu<mN)!s||(qj+tx!1+%ybp}X?rW#8oX0}kh|sL9F18na_|{3Y4y9)H4N9CZN5 Ug_ei|>i_@%07*qoM6N<$f(8wbo&W#< literal 0 HcmV?d00001 diff --git a/examples/medium/colorReplace/img/circle_trans.png b/examples/medium/colorReplace/img/circle_trans.png new file mode 100644 index 0000000000000000000000000000000000000000..ac705c412b7ee7ff19fb35f12d67923c1b2c9038 GIT binary patch literal 113 zcmeAS@N?(olHy`uVBq!ia0vp^EI`c0!NkD8C=)Yd3y{NE;1OBOz`!j8!i<;h*8Kqr zDto#(hE&{2&dA6}`0@Y0J#)`Lel`UzttKx=1~&E%MI8kO2FXy1>zvA8D}l-xJYD@< J);T3K0RTKj8+`x( literal 0 HcmV?d00001 diff --git a/examples/medium/colorReplace/img/cloud.png b/examples/medium/colorReplace/img/cloud.png new file mode 100644 index 0000000000000000000000000000000000000000..36edaeaa70e0bfef6442e0709bfd53ae3413ab91 GIT binary patch literal 524 zcmV+n0`vWeP)<h;3K|Lk000e1NJLTq002G!001@!0ssI3XZMZh00009a7bBm000tn z000tn0p4aGcmMzazDYzuRCwC$TG4I<Aqd=0-#>33+FZ7Z!+-;4o0?7U8g(22ft9<i z`@?>|K3<LMFxxc@|Ism^eFHkI9J*u2hz{s_9nS}K*mMmRV1G7=)dbv@>hq_~i_V&S z{R?#jR1|wm)UZs$8i<MCKU2;GQd42QqO-a@z^1m*=vg~64P*4vl9txX+Lk+d!wlUK zzNzKVDceb)v!-(vdZMxD`z`6LlPh6gBtw_)0NML2&8JwyawiWhj@H}Z3rE9Shc579 zPHa{ANHO}ZgCs4o)dQFN_fw;Xz^(5`kG~b0@-GtaM_=Z?wdfV?A3d4R2o`8U*QZK# zxmf1SMvrdh9jv$6OvD0r0|%i~siZ1p+)AqIlGNIir<1xYUudQ-%N3fb>yw=x>Pna2 zNnIZf8>p8gI1SWGTOsx47QX8^gm*?KXYvle0iVX3D!cs_-ph=gnX`Z2Tua@3ortca z<!#)EOXSLnK!2G(YyecT4w5>cj<<xjm%bQ8Ra6|3c<SV0X<eDCQ+3+JUxqsV4yelt zD5N=s$T{+^s4Oj)xntxoPD@b?{&;~gt@qXQvgfDv9;U&-j;6j-NBsn^JIu4;$Kx{q O0000<MNUMnLSTX<!T1ya literal 0 HcmV?d00001 diff --git a/examples/medium/colorReplace/img/roof.png b/examples/medium/colorReplace/img/roof.png new file mode 100644 index 0000000000000000000000000000000000000000..e43e5d1b06fd7e307011fea45f17fd28999a6126 GIT binary patch literal 366 zcmV-!0g?WRP)<h;3K|Lk000e1NJLTq002+`000yS0ssI3;=LUf00009a7bBm000tn z000tn0p4aGcmMzaAW1|)RCwCuSAh<NAPD5s@6TzgG(u6zu=QSJjd$-xqIf8Qs9}T8 zi@`ge<`jiRL_SBa`omuy9X6+NI(_84@{hJvImGKE+<O=Cu;&wv>q0~C{UDzpYHFUp zrO$Z*WHFRD4Ez@Vs5vz{4$auomS}w6E7`WHn}ENUv4VI^&78(0YizE6(wCWj+GGxC zR!p?XXFdx4`ghvkhZBY);jLyI>su43z>#(3`Wj!cAK)L2*>%|YKL0NtRuXETQLB8u z$bUV4CwVf?iuds7__?c_eAz)r$Ql{?*|?pcrz?^}g+#-B6JjGy*VhSqE>C3hQES7J zk8ZOs_-4Pi<HMMANTJ?L9tgCbuXo?)KeNXWwkIFPt@0p8fBzzX0k4d-lEBAwKL7v# M07*qoM6N<$g3XSm^8f$< literal 0 HcmV?d00001 diff --git a/examples/medium/colorReplace/img/square.png b/examples/medium/colorReplace/img/square.png new file mode 100644 index 0000000000000000000000000000000000000000..0bb9c43f89a3b63bda3c4399d6f1d9430f3b1c42 GIT binary patch literal 103 zcmeAS@N?(olHy`uVBq!ia0vp^EI`c0!NkD8C=)Yd3y{NE;1OBOz`!j8!i<;h*8Kqr zN_x6DhE&{2{_+36J+o9>5HBz93=x(GPZ=1*((F#pJovsEsEEPS)z4*}Q$iB}Ok5h7 literal 0 HcmV?d00001 diff --git a/examples/medium/colorReplace/img/star_trans.png b/examples/medium/colorReplace/img/star_trans.png new file mode 100644 index 0000000000000000000000000000000000000000..e136dc302a9bf39cdbe3205f287fd1a915b98e89 GIT binary patch literal 107 zcmeAS@N?(olHy`uVBq!ia0vp^EI`c0!NkD8C=)Yd3y{NE;1OBOz`!j8!i<;h*8Kqr z%6hsuhE&{2&dA6}a5(n=AcKozrH6=sa|B0gL<+;Lokov${xW|6RLJ1z>gTe~DWM4f Dzt$YA literal 0 HcmV?d00001 diff --git a/examples/medium/colorReplace/src/asm/macros/cpct_reverseBits.s b/examples/medium/colorReplace/src/asm/macros/cpct_reverseBits.s new file mode 100644 index 000000000..35c643fde --- /dev/null +++ b/examples/medium/colorReplace/src/asm/macros/cpct_reverseBits.s @@ -0,0 +1,263 @@ +;;-----------------------------LICENSE NOTICE------------------------------------ +;; This file is part of CPCtelera: An Amstrad CPC Game Engine +;; Copyright (C) 2016 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) +;; +;; This program is free software: you can redistribute it and/or modify +;; it under the terms of the GNU Lesser General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU Lesser General Public License for more details. +;; +;; You should have received a copy of the GNU Lesser General Public License +;; along with this program. If not, see <http://www.gnu.org/licenses/>. +;;------------------------------------------------------------------------------- + +;; +;; File: Reverse Bits +;; +;; Useful macros for bit reversing and selecting in different ways. Only +;; valid to be used from assembly language (not from C). +;; + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Macro: cpctm_reverse_and_select_bits_of_A +;; +;; Reorders the bits of A and mixes them letting the user select the +;; new order for the bits by using a selection mask. +;; +;; Parameters: +;; TReg - An 8-bits register that will be used for intermediate calculations. +;; This register may be one of these: B, C, D, E, H, L +;; SelectionMask - An 8-bits mask that will be used to select the bits to get from +;; the reordered bits. It might be an 8-bit register or even (hl). +;; +;; Input Registers: +;; A - Byte to be reversed +;; TReg - Should have a copy of A (same exact value) +;; +;; Return Value: +;; A - Resulting value with bits reversed and selected +;; +;; Details: +;; This macro reorders the bits in A and mixes them with the same bits in +;; their original order by using a *SelectionMask*. The process is as follows: +;; +;; 1. Consider the 8 bits of A = TReg = [01234567] +;; 2. Reorder the 8 bits of A, producing A2 = [32547610] +;; 2. Reorder the bits of TReg, producing TReg2 = [76103254] +;; 3. Combines both reorders into final result using a *SelectionMask*. Each +;; 0 bit from the selection mask means "select bit from A2", whereas each 1 bit +;; means "select bit from TReg2". +;; +;; For instance, a selection mask 0b11001100 will produce this result: +;; +;; (start code) +;; A2 = [ 32 54 76 10 ] +;; TReg2 = [ 76 10 32 54 ] +;; SelMask = [ 11 00 11 00 ] // 1 = TReg2-bits, 0 = A2-bits +;; --------------------------- +;; Result = [ 76 54 32 10 ] +;; (end code) +;; +;; Therefore, mask 0b11001100 produces the effect of reversing the bits of A +;; completely. Other masks will produce different reorders of the bits in A, for +;; different requirements or needs. +;; +;; Modified Registers: +;; AF, TReg +;; +;; Required memory: +;; 16 bytes +;; +;; Time Measures: +;; (start code) +;; Case | microSecs(us) | CPU Cycles +;; ------------------------------------ +;; Any | 16 | 64 +;; ------------------------------------ +;; (end code) +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +.macro cpctm_reverse_and_select_bits_of_A TReg, SelectionMask + rlca ;; [1] | Rotate left twice so that... + rlca ;; [1] | ... A=[23456701] + + ;; Mix bits of TReg and A so that all bits are in correct relative order + ;; but displaced from their final desired location + xor TReg ;; [1] TReg = [01234567] (original value) + and #0b01010101 ;; [2] A = [23456701] (bits rotated twice left) + xor TReg ;; [1] A2 = [03254761] (TReg mixed with A to get bits in order) + + ;; Now get bits 54 and 10 in their right location and save them into TReg + rlca ;; [1] A = [ 32 54 76 10 ] (54 and 10 are in their desired place) + ld TReg, a ;; [1] TReg = A (Save this bit location into TReg) + + ;; Now get bits 76 and 32 in their right location in A + rrca ;; [1] | Rotate A right 4 times to... + rrca ;; [1] | ... get bits 76 and 32 located at their ... + rrca ;; [1] | ... desired location : + rrca ;; [1] | ... A = [ 76 10 32 54 ] (76 and 32 are in their desired place) + + ;; Finally, mix bits from TReg and A to get all bits reversed and selected + xor TReg ;; [1] TReg = [32547610] (Mixed bits with 54 & 10 in their right place) + and SelectionMask ;; [2] A = [76103254] (Mixed bits with 76 & 32 in their right place) + xor TReg ;; [1] A2 = [xxxxxxxx] final value: bits of A reversed and selected using *SelectionMask* +.endm + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Macro: cpctm_reverse_bits_of_A +;; Macro: cpctm_reverse_mode_2_pixels_of_A +;; +;; Reverses the 8-bits of A, from [01234567] to [76543210]. This also reverses +;; all pixels contained in A when A is in screen pixel format, mode 2. +;; +;; Parameters: +;; TReg - An 8-bits register that will be used for intermediate calculations. +;; This register may be one of these: B, C, D, E, H, L +;; +;; Input Registers: +;; A - Byte to be reversed +;; TReg - Should have a copy of A (same exact value) +;; +;; Return Value: +;; A - Resulting value with bits reversed +;; +;; Requires: +;; - Uses the macro <cpctm_reverse_and_select_bits_of_A>. +;; +;; Details: +;; This macro reverses the bits in A. If bits of A = [01234567], the final +;; result after processing this macro will be A = [76543210]. Register TReg is +;; used for intermediate calculations and its value is destroyed. +;; +;; Modified Registers: +;; AF, TReg +;; +;; Required memory: +;; 16 bytes +;; +;; Time Measures: +;; (start code) +;; Case | microSecs(us) | CPU Cycles +;; ------------------------------------ +;; Any | 16 | 64 +;; ------------------------------------ +;; (end code) +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +.macro cpctm_reverse_bits_of_A TReg + cpctm_reverse_and_select_bits_of_A TReg, #0b11001100 +.endm +.macro cpctm_reverse_mode_2_pixels_of_A TReg + cpctm_reverse_bits_of_A TReg +.endm + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Macro: cpctm_reverse_mode_1_pixels_of_A +;; +;; Reverses the order of pixel values contained in register A, assuming A is +;; in screen pixel format, mode 1. +;; +;; Parameters: +;; TReg - An 8-bits register that will be used for intermediate calculations. +;; This register may be one of these: B, C, D, E, H, L +;; +;; Input Registers: +;; A - Byte with pixel values to be reversed +;; TReg - Should have a copy of A (same exact value) +;; +;; Return Value: +;; A - Resulting byte with the 4 pixels values reversed in order +;; +;; Requires: +;; - Uses the macro <cpctm_reverse_and_select_bits_of_A>. +;; +;; Details: +;; This macro considers that A contains a byte that codifies 4 pixels in +;; screen pixel format, mode 1. It modifies A to reverse the order of its 4 +;; contained pixel values left-to-right (1234 -> 4321). With respect to the +;; order of the 8-bits of A, the concrete operations performed is: +;; (start code) +;; A = [012345678] == reverse-pixels ==> [10326587] = A2 +;; (end code) +;; You may want to check <cpct_px2byteM1> to know how bits codify both pixels +;; in one single byte for screen pixel format, mode 1. +;; +;; *TReg* is an 8-bit register that will be used for intermediate calculations, +;; destroying its original value (that should be same as A, at the start). +;; +;; Modified Registers: +;; AF, TReg +;; +;; Required memory: +;; 16 bytes +;; +;; Time Measures: +;; (start code) +;; Case | microSecs(us) | CPU Cycles +;; ------------------------------------ +;; Any | 16 | 64 +;; ------------------------------------ +;; (end code) +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +.macro cpctm_reverse_mode_1_pixels_of_A TReg + cpctm_reverse_and_select_bits_of_A TReg, #0b00110011 +.endm + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Macro: cpctm_reverse_mode_0_pixels_of_A +;; +;; Reverses the order of pixel values contained in register A, assuming A is +;; in screen pixel format, mode 0. +;; +;; Parameters: +;; TReg - An 8-bits register that will be used for intermediate calculations. +;; This register may be one of these: B, C, D, E, H, L +;; +;; Input Registers: +;; A - Byte with pixel values to be reversed +;; TReg - Should have a copy of A (same exact value) +;; +;; Return Value: +;; A - Resulting byte with the 2 pixels values reversed in order +;; +;; Details: +;; This macro considers that A contains a byte that codifies 2 pixels in +;; screen pixel format, mode 0. It modifies A to reverse the order of its 2 +;; contained pixel values left-to-right (12 -> 21). With respect to the +;; order of the 8-bits of A, the concrete operation performed is: +;; (start code) +;; A = [012345678] == reverse-pixels ==> [10325476] = A2 +;; (end code) +;; You may want to check <cpct_px2byteM0> to know how bits codify both pixels +;; in one single byte for screen pixel format, mode 0. +;; +;; *TReg* is an 8-bit register that will be used for intermediate calculations, +;; destroying its original value (that should be same as A, at the start). +;; +;; Modified Registers: +;; AF, TReg +;; +;; Required memory: +;; 7 bytes +;; +;; Time Measures: +;; (start code) +;; Case | microSecs(us) | CPU Cycles +;; ------------------------------------ +;; Any | 7 | 28 +;; ------------------------------------ +;; (end code) +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +.macro cpctm_reverse_mode_0_pixels_of_A TReg + rlca ;; [1] | Rotate A twice to the left to get bits ordered... + rlca ;; [1] | ... in the way we need for mixing, A = [23456701] + + ;; Mix TReg with A to get pixels reversed by reordering bits + xor TReg ;; [1] | TReg = [01234567] + and #0b01010101 ;; [2] | A = [23456701] + xor TReg ;; [1] | A2 = [03254761] + rrca ;; [1] Rotate right to get pixels reversed A = [10325476] +.endm \ No newline at end of file diff --git a/examples/medium/colorReplace/src/asm/macros/cpct_undocumentedOpcodes.s b/examples/medium/colorReplace/src/asm/macros/cpct_undocumentedOpcodes.s new file mode 100644 index 000000000..258e16fbd --- /dev/null +++ b/examples/medium/colorReplace/src/asm/macros/cpct_undocumentedOpcodes.s @@ -0,0 +1,97 @@ +;;-----------------------------LICENSE NOTICE------------------------------------ +;; This file is part of CPCtelera: An Amstrad CPC Game Engine +;; Copyright (C) 2016 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) +;; +;; This program is free software: you can redistribute it and/or modify +;; it under the terms of the GNU Lesser General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU Lesser General Public License for more details. +;; +;; You should have received a copy of the GNU Lesser General Public License +;; along with this program. If not, see <http://www.gnu.org/licenses/>. +;;------------------------------------------------------------------------------- + +;; +;; File: Undocumented Opcodes +;; +;; Macros to clarify source code when using undocumented opcodes. Only +;; valid to be used from assembly language (not from C). +;; + +;; Macro: jr__0 +;; Opcode for "JR #0" instruction +;; +.macro jr__0 + .DW #0x0018 ;; JR #00 (Normally used as a modifiable jump, as jr 0 is an infinite loop) +.endm + +;; Macro: ld__ixl_c +;; Opcode for "LD IXL, C" instruction +;; +.macro ld__ixl_c + .DW #0x69DD ;; ld ixl, c +.endm + +;; Macro: ld__c_ixl +;; Opcode for "LD C, IXL" instruction +;; +.macro ld__c_ixl + .DW #0x4DDD ;; ld c, ixl +.endm + +;; Macro: ld__ixl_b +;; Opcode for "LD IXL, B" instruction +;; +.macro ld__ixl_b + .DW #0x68DD ;; ld ixl, b +.endm + +;; Macro: ld__b_ixl +;; Opcode for "LD B, IXL" instruction +;; +.macro ld__b_ixl + .DW #0x45DD ;; ld b, ixl +.endm + +;; Macro: ld__a_ixl +;; Opcode for "LD A, IXL" instruction +;; +.macro ld__a_ixl + .dw #0x7DDD ;; Opcode for ld a, ixl +.endm + +;; Macro: ld__ixl_a +;; Opcode for "LD IXL, A" instruction +;; +.macro ld__ixl_a + .dw #0x6FDD ;; Opcode for ld ixl, a +.endm + +;; Macro: dec__ixh +;; Opcode for "DEC IXH" instruction +;; +.macro dec__ixh + .dw #0x25DD ;; Opcode for dec ixh +.endm + +;; Macro: dec__ixl +;; Opcode for "DEC IXL" instruction +;; +.macro dec__ixl + .dw #0x2DDD ;; Opcode for dec ixl +.endm + +;; Macro: ld__ixl Value +;; Opcode for "LD IXL, Value" instruction +;; +;; Parameters: +;; Value - An inmediate 8-bits value that will be loaded into IXL +;; +.macro ld__ixl Value + .db #0xDD, #0x2E, Value ;; Opcode for ld ixl, Value +.endm diff --git a/examples/medium/colorReplace/src/asm/sprites/colorReplace/M0/cpct_drawSpriteColorizeM0.asm b/examples/medium/colorReplace/src/asm/sprites/colorReplace/M0/cpct_drawSpriteColorizeM0.asm new file mode 100644 index 000000000..01cb1f2b5 --- /dev/null +++ b/examples/medium/colorReplace/src/asm/sprites/colorReplace/M0/cpct_drawSpriteColorizeM0.asm @@ -0,0 +1,203 @@ +;;-----------------------------LICENSE NOTICE------------------------------------ +;; This file is part of CPCtelera: An Amstrad CPC Game Engine +;; Copyright (C) 2017 Arnaud Bouche (Arnaud6128) +;; Copyright (C) 2017 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) +;; +;; This program is free software: you can redistribute it and/or modify +;; it under the terms of the GNU Lesser General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU Lesser General Public License for more details. +;; +;; You should have received a copy of the GNU Lesser General Public License +;; along with this program. If not, see <http://www.gnu.org/licenses/>. +;;------------------------------------------------------------------------------- +.module cpct_sprites + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; +;; Function: cpct_drawSpriteColorizeM0 +;; +;; Directly replace a color and draw a sprite to video memory. +;; +;; C Definition: +;; void <cpct_drawSpriteColorizeM0> (void* *sprite*, void* *memory*, <u8> *width*, <u8> *height*, <u8> *oldColor*, <u8> *newColor*) __z88dk_callee; +;; +;; Input Parameters (8 bytes): +;; (2B HL') sprite - Source Sprite Pointer (array of pixel data) +;; (2B DE') memory - Destination video memory pointer +;; (1B C' ) height - Sprite Height in bytes (>0) +;; (1B B' ) width - Sprite Width in *bytes* (Beware, *not* in pixels!) +;; (1B L ) oldColor - Color to replace +;; (1B H ) newColor - New color +;; +;; Assembly call (Input parameters on registers): +;; > call cpct_drawSpriteColorizeM0_asm +;; +;; Parameter Restrictions: +;; * *sprite* must be an array containing sprite's pixels data in screen pixel format. +;; Sprite must be rectangular and all bytes in the array must be consecutive pixels, +;; starting from top-left corner and going left-to-right, top-to-bottom down to the +;; bottom-right corner. Total amount of bytes in pixel array should be *width* x *height*. +;; * *memory* could be any place in memory, inside or outside current video memory. It +;; will be equally treated as video memory (taking into account CPC's video memory +;; disposition). This lets you copy sprites to software or hardware backbuffers, and +;; not only video memory. +;; * *width* must be the width of the sprite *in bytes*. Always remember that the width must be +;; expressed in bytes and *not* in pixels. +;; The correspondence is mode 0 : 1 byte = 2 pixels +;; * *height* must be the height of the sprite in bytes, and must be greater than 0. +;; There is no practical upper limit to this value. Height of a sprite in +;; bytes and pixels is the same value, as bytes only group consecutive pixels in +;; the horizontal space. +;; * *oldColor* must be the index of color (0 to 15) to replace +;; * *newColor* must be the index of the new color (0 to 15) +;; +;; Known limitations: +;; * This function does not do any kind of boundary check or clipping. If you +;; try to draw sprites on the frontier of your video memory or screen buffer +;; if might potentially overwrite memory locations beyond boundaries. This +;; could cause your program to behave erratically, hang or crash. Always +;; take the necessary steps to guarantee that you are drawing inside screen +;; or buffer boundaries. +;; * As this function receives a byte-pointer to memory, it can only +;; draw byte-sized and byte-aligned sprites. This means that the box cannot +;; start on non-byte aligned pixels (like odd-pixels, for instance) and +;; their sizes must be a multiple of a byte (2 in mode 0, 4 in mode 1 and +;; 8 in mode 2). +;; * This function *will not work from ROM*, as it uses self-modifying code. +;; * This function requires the CPC firmware to be DISABLED. Otherwise, random crashes might happen due to side effects. +;; +;; Destroyed Register values: +;; AF, BC, DE, HL, BC', DE', HL', IX +;; +;; Required memory: +;; C-bindings - 118 bytes +;; ASM-bindings - 108 bytes +;; +;; Time Measures: +;; (start code) +;; Case | microSecs (us) | CPU Cycles +;; ---------------------------------------------------------------- +;; | 29 + (62 + 23W)H | 116 + (248 + 92W)H +;; ---------------------------------------------------------------- +;; W=2,H=16 | 1757 | 7028 +;; W=4,H=32 | 4957 | 19828 +;; ---------------------------------------------------------------- +;; Asm saving | -16 | -64 +;; ---------------------------------------------------------------- +;; (end code) +;; W = *width* in bytes, H = *height* in bytes, HH = [(H-1)/8] +;; +;; Credits: +;; Original routine optimized by @Docent and discussed in CPCWiki : +;; http://www.cpcwiki.eu/forum/programming/cpctelera-colorize-sprite/ +;; +;; Thanks to all of them for their help and support. +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +.globl dc_mode0_ct + +;; Macro to convert Pixel to xAxC xBxD format +.macro convertPixel + ;; From cpct_px2byteM0 + ld bc, #dc_mode0_ct ;; [3] BC points to conversion table (dc_mode0_ct) + + ;; Compute BC += A + add c ;; [1] | C += A + ld c, a ;; [1] | + sub a ;; [1] A = 0 (preserving Carry Flag) + adc b ;; [1] | B += Carry + ld b, a ;; [1] | + + ;; A = *(BC + A) + ld a, (bc) ;; [2] A = Value stored at the table pointed by BC +.endm + + ;; Convert newColor to pixel format (E) + ld a, h ;; [1] A = H new color index + convertPixel ;; [10] | Convert into A + ld e, a ;; [1] | E = A new color : xAxC xBxD + + ;; Convert oldColor to pixel format (D) + ld a, l ;; [1] A = L old color index + convertPixel ;; [10] | Convert into A + ld d, a ;; [1] | D = A old color : xAxC xBxD + + ld c, #0x55 ;; [2] C = Mask to get pixel A : xAxC xBxD + + exx ;; [1] Switch to Alternate registers + + ld__ixl_c ;; [1] IXL = C (Width) + ld c, b ;; [1] C = B (Height) + +convertLoop: + ld (startLine), de ;; [6] Store DE start line (DestMem) + ld__b_ixl ;; [2] B = IXL (Sprite Width) + +lineLoop: + ld a, (hl) ;; [2] A = (HL) current Byte of sprite + exx ;; [1] Switch to Default registers + + ld l, a ;; [1] L = A current Byte of sprite : ABAB ABAB + and c ;; [2] A |= C (C = 0x55) : xBxB xBxB + + cp d ;; [1] Test if pixel (A) is the old colour to be replaced (D) + jr nz, readPixelA ;; [2/3] If not equal go to next pixel + ld a, e ;; [1] else A = new colour to set (E) + +;; Pixel Mode 0 = ABAB ABAB +readPixelA: + ld h, a ;; [1] H = A (current colorized sprite) : xBxB xBxB + ld a, l ;; [1] L = A current Byte of sprite : ABAB ABAB + rrca ;; [1] A (current byte of sprite) >> 1 : ABAB ABAB -> xABA BABA + and c ;; [2] A |= Mask (0x55) : xAxA xAxA + + cp d ;; [1] Test if pixel (A) is the old colour to be replaced (D) + jr nz, readPixelB ;; [2/3] If not equal go to next pixel + ld a, e ;; [1] else A = new colour to set (E) + +readPixelB: + rlca ;; [1] A = xAxA xAxA << 1 : AxAx AxAx + or h ;; [1] A |= H (xBxB xBxB) : ABAB ABAB + + exx ;; [1] Switch to Alternate registers + +drawByte: + ld (de), a ;; [2] Update current sprite byte with pixels + inc hl ;; [2] Next byte sprite source + inc de ;; [2] Next byte sprite colorized + djnz lineLoop ;; [3] Decrement B (Width) if B != 0 goto lineLoop + + dec c ;; [1] Decrement C (Height) + jr z, end ;; [2/3] If C == O goto end + +startLine = .+1 ;; Placeholder for the Start line adress + ld de, #0000 ;; [3] DE = Start Line + + ld a, d ;; [1] Start of next pixel line normally is 0x0800 bytes away. + add #0x08 ;; [2] so we add it to DE (just by adding 0x08 to D) + ld d, a ;; [1] + and #0x38 ;; [2] We check if we have crossed memory boundary (every 8 pixel lines).. + + jr nz, convertLoop ;; [2/3] .. by checking the 4 bits that identify present memory line. + ;; .... If 0, we have crossed boundaries + +dms_sprite_8bit_boundary_crossed: + ld a, e ;; [1] DE = DE + 0xC050h + add #0x50 ;; [2] -- Relocate DE pointer to the start of the next pixel line: + ld e, a ;; [1] -- DE is moved forward 3 memory banks plus 50 bytes (4000h * 3) + ld a, d ;; [1] -- which effectively is the same as moving it 1 bank backwards and then + adc #0xC0 ;; [2] -- 50 bytes forwards (which is what we want to move it to the next pixel line) + ld d, a ;; [1] -- Calculations are made with 8 bit maths as it is faster than other alternatives here + + jr convertLoop ;; [3] Jump to continue with next pixel line + +end: + ;; Return is included in bindings + + diff --git a/examples/medium/colorReplace/src/asm/sprites/colorReplace/M0/cpct_drawSpriteColorizeM0_asmbindings.s b/examples/medium/colorReplace/src/asm/sprites/colorReplace/M0/cpct_drawSpriteColorizeM0_asmbindings.s new file mode 100644 index 000000000..d5930a9aa --- /dev/null +++ b/examples/medium/colorReplace/src/asm/sprites/colorReplace/M0/cpct_drawSpriteColorizeM0_asmbindings.s @@ -0,0 +1,36 @@ +;;-----------------------------LICENSE NOTICE------------------------------------ +;; This file is part of CPCtelera: An Amstrad CPC Game Engine +;; Copyright (C) 2017 Arnaud Bouche (Arnaud6128) +;; Copyright (C) 2017 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) +;; +;; This program is free software: you can redistribute it and/or modify +;; it under the terms of the GNU Lesser General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU Lesser General Public License for more details. +;; +;; You should have received a copy of the GNU Lesser General Public License +;; along with this program. If not, see <http://www.gnu.org/licenses/>. +;;------------------------------------------------------------------------------- +.module cpct_sprites + +.include "../../../macros/cpct_undocumentedOpcodes.s" + +;; +;; ASM bindings for <cpct_drawSpriteColorizeM0> +;; +cpct_drawSpriteColorizeM0_asm:: ;; Assembly entry point + + ;; GET Parameters from the stack + ld (dms_restore_ix + 2), ix ;; [6] Save IX to restore it before returning + pop hl ;; [3] HL = Return Address + +;;.include /cpct_drawSpriteColorizeM0.asm/ + +dms_restore_ix: + ld ix, #0000 ;; [4] Restore IX before returning + ret ;; [3] Return to caller \ No newline at end of file diff --git a/examples/medium/colorReplace/src/asm/sprites/colorReplace/M0/cpct_drawSpriteColorizeM0_cbindings.s b/examples/medium/colorReplace/src/asm/sprites/colorReplace/M0/cpct_drawSpriteColorizeM0_cbindings.s new file mode 100644 index 000000000..ac5d57084 --- /dev/null +++ b/examples/medium/colorReplace/src/asm/sprites/colorReplace/M0/cpct_drawSpriteColorizeM0_cbindings.s @@ -0,0 +1,48 @@ +;;-----------------------------LICENSE NOTICE------------------------------------ +;; This file is part of CPCtelera: An Amstrad CPC Game Engine +;; Copyright (C) 2017 Arnaud Bouche (Arnaud6128) +;; Copyright (C) 2017 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) +;; +;; This program is free software: you can redistribute it and/or modify +;; it under the terms of the GNU Lesser General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU Lesser General Public License for more details. +;; +;; You should have received a copy of the GNU Lesser General Public License +;; along with this program. If not, see <http://www.gnu.org/licenses/>. +;;------------------------------------------------------------------------------- +.module cpct_sprites + +.include "../../../macros/cpct_undocumentedOpcodes.s" + +;; +;; C bindings for <cpct_drawSpriteColorizeM0> +;; +;; 33 us, 10 bytes +;; +_cpct_drawSpriteColorizeM0:: + + ;; GET Parameters from the stack + ld (dms_restore_ix + 2), ix ;; [6] Save IX to restore it before returning + pop hl ;; [3] HL = Return Address + + exx + pop hl ;; [3] HL' = Source address (Sprite) + pop de ;; [3] DE' = Destination Memory + pop bc ;; [5] BC' = (B = Sprite Height, C = Width) + exx + + ex (sp), hl ;; [6] HL = (H = newColor, L = oldColor) + ;; ... and leave Return Address at (SP) as we don't need to restore + ;; ... stack status because callin convention is __z88dk_callee + +.include /cpct_drawSpriteColorizeM0.asm/ + +dms_restore_ix: + ld ix, #0000 ;; [4] Restore IX before returning + ret ;; [3] Return to caller \ No newline at end of file diff --git a/examples/medium/colorReplace/src/asm/sprites/colorReplace/M0/cpct_drawSpriteMaskedAlignedColorizeM0.asm b/examples/medium/colorReplace/src/asm/sprites/colorReplace/M0/cpct_drawSpriteMaskedAlignedColorizeM0.asm new file mode 100644 index 000000000..93b252423 --- /dev/null +++ b/examples/medium/colorReplace/src/asm/sprites/colorReplace/M0/cpct_drawSpriteMaskedAlignedColorizeM0.asm @@ -0,0 +1,215 @@ +;;-----------------------------LICENSE NOTICE------------------------------------ +;; This file is part of CPCtelera: An Amstrad CPC Game Engine +;; Copyright (C) 2017 Arnaud Bouche (Arnaud6128) +;; Copyright (C) 2017 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) +;; +;; This program is free software: you can redistribute it and/or modify +;; it under the terms of the GNU Lesser General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU Lesser General Public License for more details. +;; +;; You should have received a copy of the GNU Lesser General Public License +;; along with this program. If not, see <http://www.gnu.org/licenses/>. +;;------------------------------------------------------------------------------- +.module cpct_sprites + +.globl dc_mode0_ct + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; +;; Function: cpct_drawSpriteMaskedAlignedColorizeM0 +;; +;; Directly replace a color and draw a sprite Masked Aligned to video memory. +;; +;; C Definition: +;; void <cpct_drawSpriteMaskedAlignedColorizeM0> (void* *sprite*, void* *memory*, <u8> *width*, <u8> *height*, +;; <u8> *oldColor*, <u8> *newColor*, <u8*> *pmasktable*) __z88dk_callee; +;; +;; Input Parameters (10 bytes): +;; (2B HL') sprite - Source Sprite Pointer (array of pixel data) +;; (2B DE') memory - Destination video memory pointer +;; (1B C' ) height - Sprite Height in bytes (>0) +;; (1B B' ) width - Sprite Width in *bytes* (Beware, *not* in pixels!) +;; (1B E ) oldColor - Color to replace +;; (1B D ) newColor - New color +;; (2B HL) pmasktable - Pointer to the aligned mask table used to create transparency +;; +;; Assembly call (Input parameters on registers): +;; > call cpct_drawSpriteMaskedAlignedColorizeM0_asm +;; +;; Parameter Restrictions: +;; * *sprite* must be an array containing sprite's pixels data in screen pixel format +;; Sprite must be rectangular and all bytes in the array must be consecutive pixels, +;; starting from top-left corner and going left-to-right, top-to-bottom down to the +;; bottom-right corner. Total amount of bytes in pixel array should be *width* x *height*. +;; * *memory* could be any place in memory, inside or outside current video memory. It +;; will be equally treated as video memory (taking into account CPC's video memory +;; disposition). This lets you copy sprites to software or hardware backbuffers, and +;; not only video memory. +;; * *width* must be the width of the sprite *in bytes*. Always remember that the width must be +;; expressed in bytes and *not* in pixels. +;; The correspondence is mode 0 : 1 byte = 2 pixels +;; * *height* must be the height of the sprite in bytes, and must be greater than 0. +;; There is no practical upper limit to this value. Height of a sprite in +;; bytes and pixels is the same value, as bytes only group consecutive pixels in +;; the horizontal space. +;; * *oldColor* must be the index of color (0 to 15) to replace +;; * *newColor* must be the index of the new color (0 to 15) +;; +;; Known limitations: +;; * This function does not do any kind of boundary check or clipping. If you +;; try to draw sprites on the frontier of your video memory or screen buffer +;; if might potentially overwrite memory locations beyond boundaries. This +;; could cause your program to behave erratically, hang or crash. Always +;; take the necessary steps to guarantee that you are drawing inside screen +;; or buffer boundaries. +;; * As this function receives a byte-pointer to memory, it can only +;; draw byte-sized and byte-aligned sprites. This means that the box cannot +;; start on non-byte aligned pixels (like odd-pixels, for instance) and +;; their sizes must be a multiple of a byte (2 in mode 0, 4 in mode 1 and +;; 8 in mode 2). +;; * This function *will not work from ROM*, as it uses self-modifying code. +;; * This function requires the CPC firmware to be DISABLED. Otherwise, random crashes might happen due to side effects. +;; +;; Destroyed Register values: +;; AF, BC, DE, HL, BC', DE', HL', IX +;; +;; Required memory: +;; C-bindings - 112 bytes +;; ASM-bindings - 96 bytes +;; +;; Time Measures: +;; (start code) +;; Case | microSecs (us) | CPU Cycles +;; ---------------------------------------------------------------- +;; | 32 + (58 + 20W)H | 128 + (232 + 80W)H +;; ---------------------------------------------------------------- +;; W=2,H=16 | 1600 | 6400 +;; W=4,H=32 | 4448 | 17792 +;; ---------------------------------------------------------------- +;; Asm saving | -16 | -64 +;; ---------------------------------------------------------------- +;; (end code) +;; W = *width* in bytes, H = *height* in bytes, HH = [(H-1)/8] +;; +;; Credits: +;; Original routine optimized by @Docent and discussed in CPCWiki : +;; http://www.cpcwiki.eu/forum/programming/cpctelera-colorize-sprite/ +;; +;; Thanks to all of them for their help and support. +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;; Macro to convert Pixel to xAxC xBxD format +.macro convertPixel + ;; From cpct_px2byteM0 + ld bc, #dc_mode0_ct ;; [3] BC points to conversion table (dc_mode0_ct) + + ;; Compute BC += A + add c ;; [1] | C += A + ld c, a ;; [1] | + sub a ;; [1] A = 0 (preserving Carry Flag) + adc b ;; [1] | B += Carry + ld b, a ;; [1] | + + ;; A = *(BC + A) + ld a, (bc) ;; [2] A = Value stored at the table pointed by BC +.endm + + ;; Convert newColor to pixel format (E) + ld a, h ;; [1] A = H new color index + convertPixel ;; [10] | Convert into A + ld e, a ;; [1] | E = A new color : xAxC xBxD + + ;; Convert oldColor to pixel format (D) + ld a, l ;; [1] A = L old color index + convertPixel ;; [10] | Convert into A + ld b, d + ld d, a ;; [1] | D = A old color : xAxC xBxD + + ld c, #0x55 ;; [2] C = Mask to get pixel A : xAxC xBxD + exx ;; [1] Switch to Alternate registers + + ld__ixl_c ;; [1] IXL = C (Width) + ld c, b ;; [1] C = B (Height) + +convertLoop: + push de ;; [4] Store DE start line (DestMem) + ld__b_ixl ;; [2] B = IXL (Sprite Width) + +lineLoop: + ld a, (hl) ;; [2] A = (HL) current Byte of sprite + exx ;; [1] Switch to Default registers + + ld l, a ;; [1] L = A current Byte of sprite : ABAB ABAB + and c ;; [2] A |= C (C = 0x55) : xBxB xBxB + + cp d ;; [1] Test if pixel (A) is the old colour to be replaced (D) + jr nz, readPixelA ;; [2/3] If not equal go to next pixel + ld a, e ;; [1] else A = new colour to set (E) + +;; Pixel Mode 0 = ABAB ABAB +readPixelA: + ld h, a ;; [1] H = A (current colorized sprite) : xBxB xBxB + ld a, l ;; [1] L = A current Byte of sprite : ABAB ABAB + rrca ;; [1] A (current byte of sprite) >> 1 : ABAB ABAB -> xABA BABA + and c ;; [2] A |= Mask (0x55) : xAxA xAxA + + cp d ;; [1] Test if pixel (A) is the old colour to be replaced (D) + jr nz, readPixelB ;; [2/3] If not equal go to next pixel + ld a, e ;; [1] else A = new colour to set (E) + +readPixelB: + rlca ;; [1] A = xAxA xAxA << 1 : AxAx AxAx + or h ;; [1] A |= H (xBxB xBxB) : ABAB ABAB + +drawByte: + ld h, b ;; [1] H = B (Masked table adress High Byte) + ld l, a ;; [1] Access mask table element (table must be 256-byte aligned) + exx ;; [1] Switch to Alternate registers + + ld a, (de) ;; [2] Get the value of the byte of the screen where we are going to draw + exx ;; [1] Switch to Default registers + + and (hl) ;; [2] Erase background part that is to be overwritten (Mask step 1) + or l ;; [1] Add up background and sprite information in one byte (Mask step 2) + exx ;; [1] Switch to Alternate registers + + ld (de), a ;; [2] Save modified background + sprite data information into memory + + inc hl ;; [2] Next byte sprite source + inc de ;; [2] Next byte sprite colorized + djnz lineLoop ;; [3] Decrement B (Width) if B != 0 goto lineLoop + + dec c ;; [1] Decrement C (Height) + jr z, end ;; [2/3] If C == O goto end + + pop de ;; [3] Restore DE start line (DestMem) + + ld a, d ;; [1] Start of next pixel line normally is 0x0800 bytes away. + add #0x08 ;; [2] so we add it to DE (just by adding 0x08 to D) + ld d, a ;; [1] + and #0x38 ;; [2] We check if we have crossed memory boundary (every 8 pixel lines).. + + jr nz, convertLoop ;; [2/3] .. by checking the 4 bits that identify present memory line. + ;; .... If 0, we have crossed boundaries + +dms_sprite_8bit_boundary_crossed: + ld a, e ;; [1] DE = DE + 0xC050h + add #0x50 ;; [2] -- Relocate DE pointer to the start of the next pixel line: + ld e, a ;; [1] -- DE is moved forward 3 memory banks plus 50 bytes (4000h * 3) + ld a, d ;; [1] -- which effectively is the same as moving it 1 bank backwards and then + adc #0xC0 ;; [2] -- 50 bytes forwards (which is what we want to move it to the next pixel line) + ld d, a ;; [1] -- Calculations are made with 8 bit maths as it is faster than other alternatives here + + jr convertLoop ;; [3] Jump to continue with next pixel line + +end: + pop de ;; [3] Empty stack by getting last element (DestMem) + ;; Return is included in bindings + + diff --git a/examples/medium/colorReplace/src/asm/sprites/colorReplace/M0/cpct_drawSpriteMaskedAlignedColorizeM0_asmbindings.s b/examples/medium/colorReplace/src/asm/sprites/colorReplace/M0/cpct_drawSpriteMaskedAlignedColorizeM0_asmbindings.s new file mode 100644 index 000000000..7828b8736 --- /dev/null +++ b/examples/medium/colorReplace/src/asm/sprites/colorReplace/M0/cpct_drawSpriteMaskedAlignedColorizeM0_asmbindings.s @@ -0,0 +1,36 @@ +;;-----------------------------LICENSE NOTICE------------------------------------ +;; This file is part of CPCtelera: An Amstrad CPC Game Engine +;; Copyright (C) 2017 Arnaud Bouche (Arnaud6128) +;; Copyright (C) 2017 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) +;; +;; This program is free software: you can redistribute it and/or modify +;; it under the terms of the GNU Lesser General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU Lesser General Public License for more details. +;; +;; You should have received a copy of the GNU Lesser General Public License +;; along with this program. If not, see <http://www.gnu.org/licenses/>. +;;------------------------------------------------------------------------------- +.module cpct_sprites + +.include "../../../macros/cpct_undocumentedOpcodes.s" + +;; +;; ASM bindings for <cpct_drawSpriteMaskedAlignedColorizeM0> +;; +cpct_drawSpriteMaskedAlignedColorizeM0_asm:: ;; Assembly entry point + + ;; GET Parameters from the stack + ld (dms_restore_ix + 2), ix ;; [6] Save IX to restore it before returning + pop hl ;; [3] HL = Return Address + +.include /cpct_drawSpriteMaskedAlignedColorizeM0.asm/ + +dms_restore_ix: + ld ix, #0000 ;; [4] Restore IX before returning + ret ;; [3] Return to caller \ No newline at end of file diff --git a/examples/medium/colorReplace/src/asm/sprites/colorReplace/M0/cpct_drawSpriteMaskedAlignedColorizeM0_cbindings.s b/examples/medium/colorReplace/src/asm/sprites/colorReplace/M0/cpct_drawSpriteMaskedAlignedColorizeM0_cbindings.s new file mode 100644 index 000000000..001ae99c3 --- /dev/null +++ b/examples/medium/colorReplace/src/asm/sprites/colorReplace/M0/cpct_drawSpriteMaskedAlignedColorizeM0_cbindings.s @@ -0,0 +1,52 @@ +;;-----------------------------LICENSE NOTICE------------------------------------ +;; This file is part of CPCtelera: An Amstrad CPC Game Engine +;; Copyright (C) 2017 Arnaud Bouche (Arnaud6128) +;; Copyright (C) 2017 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) +;; +;; This program is free software: you can redistribute it and/or modify +;; it under the terms of the GNU Lesser General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU Lesser General Public License for more details. +;; +;; You should have received a copy of the GNU Lesser General Public License +;; along with this program. If not, see <http://www.gnu.org/licenses/>. +;;------------------------------------------------------------------------------- +.module cpct_sprites + +.include "../../../macros/cpct_undocumentedOpcodes.s" + +;; +;; C bindings for <cpct_drawSpriteMaskedAlignedColorizeM0> +;; +;; 39 us, 16 bytes +;; +_cpct_drawSpriteMaskedAlignedColorizeM0:: + + ;; GET Parameters from the stack + ld (dms_restore_ix + 2), ix ;; [6] Save IX to restore it before returning + pop hl ;; [3] HL = Return Address + + exx ;; [1] Switch to Alternate registers + pop hl ;; [3] HL' = Source address (Sprite) + pop de ;; [3] DE' = Destination Memory + pop bc ;; [5] BC' = (B = Sprite Height, C = Width) + + exx ;; [1] Switch to Default registers + pop de ;; [3] DE = (D = newColor, E = oldColor) + + ex (sp), hl ;; [6] HL = Table Mask address + ;; ... and leave Return Address at (SP) as we don't need to restore + ;; ... stack status because callin convention is __z88dk_callee + + ex de, hl ;; [1] HL <-> DE + +.include /cpct_drawSpriteMaskedAlignedColorizeM0.asm/ + +dms_restore_ix: + ld ix, #0000 ;; [4] Restore IX before returning + ret ;; [3] Return to caller \ No newline at end of file diff --git a/examples/medium/colorReplace/src/asm/sprites/colorReplace/M0/cpct_drawSpriteMaskedColorizeM0.asm b/examples/medium/colorReplace/src/asm/sprites/colorReplace/M0/cpct_drawSpriteMaskedColorizeM0.asm new file mode 100644 index 000000000..e954fb3dc --- /dev/null +++ b/examples/medium/colorReplace/src/asm/sprites/colorReplace/M0/cpct_drawSpriteMaskedColorizeM0.asm @@ -0,0 +1,216 @@ +;;-----------------------------LICENSE NOTICE------------------------------------ +;; This file is part of CPCtelera: An Amstrad CPC Game Engine +;; Copyright (C) 2017 Arnaud Bouche +;; Copyright (C) 2017 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) +;; +;; This program is free software: you can redistribute it and/or modify +;; it under the terms of the GNU Lesser General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU Lesser General Public License for more details. +;; +;; You should have received a copy of the GNU Lesser General Public License +;; along with this program. If not, see <http://www.gnu.org/licenses/>. +;;------------------------------------------------------------------------------- +.module cpct_sprites + +.globl dc_mode0_ct + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; +;; Function: cpct_drawSpriteMaskedColorizeM0 +;; +;; Directly replace a color and draw a sprite Masked to video memory. +;; +;; C Definition: +;; void <cpct_drawSpriteMaskedColorizeM0> (void* *sprite*, void* *memory*, <u8> *width*, <u8> *height*, <u8> *oldColor*, <u8> *newColor*) __z88dk_callee; +;; +;; Input Parameters (8 bytes): +;; (2B HL') sprite - Source Sprite Pointer (array of pixel data) +;; (2B DE') memory - Destination video memory pointer +;; (1B C' ) height - Sprite Height in bytes (>0) +;; (1B B' ) width - Sprite Width in *bytes* (Beware, *not* in pixels!) +;; (1B L ) oldColor - Color to replace +;; (1B H ) newColor - New color +;; +;; Assembly call (Input parameters on registers): +;; > call cpct_drawSpriteMaskedColorizeM0_asm +;; +;; Parameter Restrictions: +;; * *sprite* must be an array containing sprite's pixels data in screen pixel format +;; along with mask data. Each mask byte will contain enabled bits as those that should +;; be picked from the background (transparent) and disabled bits for those that will +;; be printed from sprite colour data. Each mask data byte must precede its associated +;; colour data byte. +;; Sprite must be rectangular and all bytes in the array must be consecutive pixels, +;; starting from top-left corner and going left-to-right, top-to-bottom down to the +;; bottom-right corner. Total amount of bytes in pixel array should be +;; 2 x *width* x *height* (mask data doubles array size). +;; * *memory* could be any place in memory, inside or outside current video memory. It +;; will be equally treated as video memory (taking into account CPC's video memory +;; disposition). This lets you copy sprites to software or hardware backbuffers, and +;; not only video memory. +;; * *width* must be the width of the sprite *in bytes*. Always remember that the width must be +;; expressed in bytes and *not* in pixels. +;; The correspondence is mode 0 : 1 byte = 2 pixels +;; * *height* must be the height of the sprite in bytes, and must be greater than 0. +;; There is no practical upper limit to this value. Height of a sprite in +;; bytes and pixels is the same value, as bytes only group consecutive pixels in +;; the horizontal space. +;; * *oldColor* must be the index of color (0 to 15) to replace +;; * *newColor* must be the index of the new color (0 to 15) +;; +;; Known limitations: +;; * This function does not do any kind of boundary check or clipping. If you +;; try to draw sprites on the frontier of your video memory or screen buffer +;; if might potentially overwrite memory locations beyond boundaries. This +;; could cause your program to behave erratically, hang or crash. Always +;; take the necessary steps to guarantee that you are drawing inside screen +;; or buffer boundaries. +;; * As this function receives a byte-pointer to memory, it can only +;; draw byte-sized and byte-aligned sprites. This means that the box cannot +;; start on non-byte aligned pixels (like odd-pixels, for instance) and +;; their sizes must be a multiple of a byte (2 in mode 0, 4 in mode 1 and +;; 8 in mode 2). +;; * This function *will not work from ROM*, as it uses self-modifying code. +;; * This function requires the CPC firmware to be DISABLED. Otherwise, random crashes might happen due to side effects. +;; +;; Destroyed Register values: +;; AF, BC, DE, HL, BC', DE', HL', IX +;; +;; Required memory: +;; C-bindings - 115 bytes +;; ASM-bindings - 102 bytes +;; +;; Time Measures: +;; (start code) +;; Case | microSecs (us) | CPU Cycles +;; ---------------------------------------------------------------- +;; Best | 29 + (50 + 36W)H | 116 + (200 + 144W)H +;; ---------------------------------------------------------------- +;; W=2,H=16 | 1981 | 7924 +;; W=4,H=32 | 6237 | 24948 +;; ---------------------------------------------------------------- +;; Asm saving | -16 | -64 +;; ---------------------------------------------------------------- +;; (end code) +;; W = *width* in bytes, H = *height* in bytes, HH = [(H-1)/8] +;; +;; Credits: +;; Original routine optimized by @Docent and discussed in CPCWiki : +;; http://www.cpcwiki.eu/forum/programming/cpctelera-colorize-sprite/ +;; +;; Thanks to all of them for their help and support. +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;; Macro to convert Pixel to xAxC xBxD format +.macro convertPixel + ;; From cpct_px2byteM0 + ld bc, #dc_mode0_ct ;; [3] BC points to conversion table (dc_mode0_ct) + + ;; Compute BC += A + add c ;; [1] | C += A + ld c, a ;; [1] | + sub a ;; [1] A = 0 (preserving Carry Flag) + adc b ;; [1] | B += Carry + ld b, a ;; [1] | + + ;; A = *(BC + A) + ld a, (bc) ;; [2] A = Value stored at the table pointed by BC +.endm + + ;; Convert newColor to pixel format (E) + ld a, h ;; [1] A = H new color index + convertPixel ;; [10] | Convert into A + ld e, a ;; [1] | E = A new color : xAxC xBxD + + ;; Convert oldColor to pixel format (D) + ld a, l ;; [1] A = L old color index + convertPixel ;; [10] | Convert into A + ld d, a ;; [1] | D = A old color : xAxC xBxD + + ld c, #0x55 ;; [2] C = Mask to get pixel A : xAxC xBxD + + exx ;; [1] Switch to Alternate registers + + ld__ixl_c ;; [1] IXL = C (Width) + ld c, b ;; [1] C = B (Height) + +convertLoop: + ld (startLine), de ;; [6] Store DE start line (DestMem) + ld__b_ixl ;; [2] B = IXL (Sprite Width) + +lineLoop: + inc hl ;; [2] Next byte sprite Color source + ld a, (hl) ;; [2] A = (HL) current Byte of sprite Color + dec hl ;; [2] Previous byte sprite Mask source + + exx ;; [1] Switch to Default registers + + ld l, a ;; [1] L = A current Byte of sprite : ABAB ABAB + and c ;; [2] A |= C (C = 0x55) : xBxB xBxB + + cp d ;; [1] Test if pixel (A) is the old colour to be replaced (D) + jr nz, readPixelA ;; [2/3] If not equal go to next pixel + ld a, e ;; [1] else A = new colour to set (E) + +;; Pixel Mode 0 = ABAB ABAB +readPixelA: + ld h, a ;; [1] H = A (current colorized sprite) : xBxB xBxB + ld a, l ;; [1] L = A current Byte of sprite : ABAB ABAB + rrca ;; [1] A (current byte of sprite) >> 1 : ABAB ABAB -> xABA BABA + and c ;; [2] A |= Mask (0x55) : xAxA xAxA + + cp d ;; [1] Test if pixel (A) is the old colour to be replaced (D) + jr nz, readPixelB ;; [2/3] If not equal go to next pixel + ld a, e ;; [1] else A = new colour to set (E) + +readPixelB: + rlca ;; [1] A = xAxA xAxA << 1 : AxAx AxAx + or h ;; [1] A |= H (xBxB xBxB) : ABAB ABAB + +drawByte: + exx ;; [1] Switch to Alternate registers + ld (sprite_color), a ;; [4] sprite_color = A (Sprite Byte) + + ld a, (de) ;; [2] Get next background byte into A + and (hl) ;; [2] Erase background part that is to be overwritten (Mask step 1) + inc hl ;; [3] HL += 1 => Point HL to Sprite Colour information +sprite_color = .+1 ;; Placeholder for the Sprite Color computed + or #00 ;; [2] Add up background and sprite information in one byte (Mask step 2) + ld (de), a ;; [2] Save modified background + sprite data information into memory + + inc hl ;; [2] Next byte sprite source + inc de ;; [2] Next byte Dest Memory + djnz lineLoop ;; [3] Decrement B (Width) if B != 0 goto lineLoop + + dec c ;; [1] Decrement C (Height) + jr z, end ;; [2/3] If C == O goto end + +startLine = .+1 ;; Placeholder for the Start line adress + ld de, #0000 ;; [3] DE = Start Line + + ld a, d ;; [1] Start of next pixel line normally is 0x0800 bytes away. + add #0x08 ;; [2] so we add it to DE (just by adding 0x08 to D) + ld d, a ;; [1] + and #0x38 ;; [2] We check if we have crossed memory boundary (every 8 pixel lines).. + + jr nz, convertLoop ;; [2/3] .. by checking the 4 bits that identify present memory line. + ;; .... If 0, we have crossed boundaries + +dms_sprite_8bit_boundary_crossed: + ld a, e ;; [1] DE = DE + 0xC050h + add #0x50 ;; [2] -- Relocate DE pointer to the start of the next pixel line: + ld e, a ;; [1] -- DE is moved forward 3 memory banks plus 50 bytes (4000h * 3) + ld a, d ;; [1] -- which effectively is the same as moving it 1 bank backwards and then + adc #0xC0 ;; [2] -- 50 bytes forwards (which is what we want to move it to the next pixel line) + ld d, a ;; [1] -- Calculations are made with 8 bit maths as it is faster than other alternatives here + + jr convertLoop ;; [3] Jump to continue with next pixel line + +end: + ;; Return is included in bindings \ No newline at end of file diff --git a/examples/medium/colorReplace/src/asm/sprites/colorReplace/M0/cpct_drawSpriteMaskedColorizeM0_asmbindings.s b/examples/medium/colorReplace/src/asm/sprites/colorReplace/M0/cpct_drawSpriteMaskedColorizeM0_asmbindings.s new file mode 100644 index 000000000..1a40a3186 --- /dev/null +++ b/examples/medium/colorReplace/src/asm/sprites/colorReplace/M0/cpct_drawSpriteMaskedColorizeM0_asmbindings.s @@ -0,0 +1,36 @@ +;;-----------------------------LICENSE NOTICE------------------------------------ +;; This file is part of CPCtelera: An Amstrad CPC Game Engine +;; Copyright (C) 2017 Arnaud Bouche (Arnaud6128) +;; Copyright (C) 2017 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) +;; +;; This program is free software: you can redistribute it and/or modify +;; it under the terms of the GNU Lesser General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU Lesser General Public License for more details. +;; +;; You should have received a copy of the GNU Lesser General Public License +;; along with this program. If not, see <http://www.gnu.org/licenses/>. +;;------------------------------------------------------------------------------- +.module cpct_sprites + +.include "../../../macros/cpct_undocumentedOpcodes.s" + +;; +;; ASM bindings for <cpct_drawSpriteMaskedColorizeM0> +;; +cpct_drawSpriteMaskedColorizeM0_asm:: ;; Assembly entry point + + ;; GET Parameters from the stack + ld (dms_restore_ix + 2), ix ;; [6] Save IX to restore it before returning + pop hl ;; [3] HL = Return Address + +.include /cpct_drawSpriteMaskedColorizeM0.asm/ + +dms_restore_ix: + ld ix, #0000 ;; [4] Restore IX before returning + ret ;; [3] Return to caller \ No newline at end of file diff --git a/examples/medium/colorReplace/src/asm/sprites/colorReplace/M0/cpct_drawSpriteMaskedColorizeM0_cbindings.s b/examples/medium/colorReplace/src/asm/sprites/colorReplace/M0/cpct_drawSpriteMaskedColorizeM0_cbindings.s new file mode 100644 index 000000000..c39a879a4 --- /dev/null +++ b/examples/medium/colorReplace/src/asm/sprites/colorReplace/M0/cpct_drawSpriteMaskedColorizeM0_cbindings.s @@ -0,0 +1,48 @@ +;;-----------------------------LICENSE NOTICE------------------------------------ +;; This file is part of CPCtelera: An Amstrad CPC Game Engine +;; Copyright (C) 2017 Arnaud Bouche (Arnaud6128) +;; Copyright (C) 2017 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) +;; +;; This program is free software: you can redistribute it and/or modify +;; it under the terms of the GNU Lesser General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU Lesser General Public License for more details. +;; +;; You should have received a copy of the GNU Lesser General Public License +;; along with this program. If not, see <http://www.gnu.org/licenses/>. +;;------------------------------------------------------------------------------- +.module cpct_sprites + +.include "../../../macros/cpct_undocumentedOpcodes.s" + +;; +;; C bindings for <cpct_drawSpriteMaskedColorizeM0> +;; +;; 33 us, 13 bytes +;; +_cpct_drawSpriteMaskedColorizeM0:: + + ;; GET Parameters from the stack + ld (dms_restore_ix + 2), ix ;; [6] Save IX to restore it before returning + pop hl ;; [3] HL = Return Address + + exx + pop hl ;; [3] HL' = Source address (Sprite) + pop de ;; [3] DE' = Destination Memory + pop bc ;; [5] BC' = (B = Sprite Height, C = Width) + exx + + ex (sp), hl ;; [6] HL = (H = newColor, L = oldColor) + ;; ... and leave Return Address at (SP) as we don't need to restore + ;; ... stack status because callin convention is __z88dk_callee + +.include /cpct_drawSpriteMaskedColorizeM0.asm/ + +dms_restore_ix: + ld ix, #0000 ;; [4] Restore IX before returning + ret ;; [3] Return to caller \ No newline at end of file diff --git a/examples/medium/colorReplace/src/asm/sprites/colorReplace/M0/cpct_spriteColorizeM0.asm b/examples/medium/colorReplace/src/asm/sprites/colorReplace/M0/cpct_spriteColorizeM0.asm new file mode 100644 index 000000000..790e0b6ae --- /dev/null +++ b/examples/medium/colorReplace/src/asm/sprites/colorReplace/M0/cpct_spriteColorizeM0.asm @@ -0,0 +1,166 @@ +;;-----------------------------LICENSE NOTICE------------------------------------ +;; This file is part of CPCtelera: An Amstrad CPC Game Engine +;; Copyright (C) 2017 Arnaud Bouche +;; Copyright (C) 2017 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) +;; +;; This program is free software: you can redistribute it and/or modify +;; it under the terms of the GNU Lesser General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU Lesser General Public License for more details. +;; +;; You should have received a copy of the GNU Lesser General Public License +;; along with this program. If not, see <http://www.gnu.org/licenses/>. +;;------------------------------------------------------------------------------- +.module cpct_sprites + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; +;; Function: cpct_spriteColorizeM0 +;; +;; Replace a color in a sprite and copy to another or the same sprite. +;; +;; C Definition: +;; void <cpct_spriteColorizeM0> (void* *sprite*, void* *spriteColor*, <u8> *width*, <u8> *height*, <u8> *oldColor*, <u8> *newColor*) __z88dk_callee; +;; +;; Input Parameters (6 bytes): +;; (2B HL') sprite - Source Sprite Pointer (array of pixel data) +;; (2B DE') spriteColor - Destination Sprite Pointer (can be also the Source Sprite) (array of pixel data) +;; (1B C' ) height - Sprite Height in bytes (>0) +;; (1B B' ) width - Sprite Width in *bytes* (Beware, *not* in pixels!) +;; (1B L ) oldColor - Color to replace +;; (1B H ) newColor - New color +;; +;; Assembly call (Input parameters on registers): +;; > call cpct_spriteColorizeM0_asm +;; +;; Parameter Restrictions: +;; * *sprite* must be an array containing sprite's pixels data in screen pixel format. +;; Sprite must be rectangular and all bytes in the array must be consecutive pixels, +;; starting from top-left corner and going left-to-right, top-to-bottom down to the +;; bottom-right corner. Total amount of bytes in pixel array should be *width* x *height*. +;; * *spriteColor* must be an array containing the new sprite's pixels data with the new color. +;; * *width* must be the width of the sprite *in bytes*. Always remember that the width must be +;; expressed in bytes and *not* in pixels. +;; The correspondence is mode 0 : 1 byte = 2 pixels +;; * *height* must be the height of the sprite in bytes, and must be greater than 0. +;; There is no practical upper limit to this value. Height of a sprite in +;; bytes and pixels is the same value, as bytes only group consecutive pixels in +;; the horizontal space. +;; * *oldColor* must be the index of color (0 to 15) to replace +;; * *newColor* must be the index of the new color (0 to 15) +;; +;; Known limitations: +;; * This function *will not work from ROM*, as it uses self-modifying code. +;; * This function requires the CPC firmware to be DISABLED. Otherwise, random crashes might happen due to side effects. +;; +;; Destroyed Register values: +;; AF, BC, DE, HL, BC', DE', HL', IX +;; +;; Required memory: +;; C-bindings - 81 bytes +;; ASM-bindings - 67 bytes +;; +;; Time Measures: +;; (start code) +;; Case | microSecs (us) | CPU Cycles +;; ---------------------------------------------------------------- +;; | 29 + (6 + 33W)H | 116 + (24 + 132W)H +;; ---------------------------------------------------------------- +;; W=2,H=16 | 1181 | 4724 +;; W=4,H=32 | 4445 | 17780 +;; ---------------------------------------------------------------- +;; Asm saving | -16 | -64 +;; ---------------------------------------------------------------- +;; (end code) +;; W = *width* in bytes, H = *height* in bytes +;; +;; Credits: +;; Original routine optimized by @Docent and discussed in CPCWiki : +;; http://www.cpcwiki.eu/forum/programming/cpctelera-colorize-sprite/ +;; +;; Thanks to all of them for their help and support. +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +.globl dc_mode0_ct + +;; Macro to convert Pixel to xAxC xBxD format +.macro convertPixel + ;; From cpct_px2byteM0 + ld bc, #dc_mode0_ct ;; [3] BC points to conversion table (dc_mode0_ct) + + ;; Compute BC += A + add c ;; [1] | C += A + ld c, a ;; [1] | + sub a ;; [1] A = 0 (preserving Carry Flag) + adc b ;; [1] | B += Carry + ld b, a ;; [1] | + + ;; A = *(BC + A) + ld a, (bc) ;; [2] A = Value stored at the table pointed by BC +.endm + + ;; Convert newColor to pixel format (E) + ld a, h ;; [1] A = H new color index + convertPixel ;; [10] | Convert into A + ld e, a ;; [1] | E = A new color : xAxC xBxD + + ;; Convert oldColor to pixel format (D) + ld a, l ;; [1] A = L old color index + convertPixel ;; [10] | Convert into A + ld d, a ;; [1] | D = A old color : xAxC xBxD + + ld c, #0x55 ;; [2] C = Mask to get pixel A : xAxC xBxD + exx ;; [1] Switch to Alternate registers + + ld__ixl_c ;; [1] IXL = C (Width) + ld c, b ;; [1] C = B (Height) + +convertLoop: + ld__b_ixl ;; [2] B = IXL (Sprite Width) + +lineLoop: + ld a, (hl) ;; [2] A = (HL) current Byte of sprite + exx ;; [1] Switch to Default registers + + ld l, a ;; [1] L = A current Byte of sprite : ABAB ABAB + and c ;; [2] A |= C (C = 0x55) : xBxB xBxB + + cp d ;; [1] Test if pixel (A) is the old colour to be replaced (D) + jr nz, readPixelA ;; [2/3] If not equal go to next pixel + ld a, e ;; [1] else A = new colour to set (E) + +;; Pixel Mode 0 = ABAB ABAB +readPixelA: + ld h, a ;; [1] H = A (current colorized sprite) : xBxB xBxB + ld a, l ;; [1] L = A current Byte of sprite : ABAB ABAB + rrca ;; [1] A (current byte of sprite) >> 1 : ABAB ABAB -> xABA BABA + and c ;; [2] A |= Mask (0x55) : xAxA xAxA + + cp d ;; [1] Test if pixel (A) is the old colour to be replaced (D) + jr nz, readPixelB ;; [2/3] If not equal go to next pixel + ld a, e ;; [1] else A = new colour to set (E) + +readPixelB: + rlca ;; [1] A = xAxA xAxA << 1 : AxAx AxAx + or h ;; [1] A |= H (xBxB xBxB) : ABAB ABAB + +setByte: + exx ;; [1] Switch to Alternate registers + + ld (de), a ;; [2] Update current sprite byte with pixels + inc hl ;; [2] Next byte sprite source + inc de ;; [2] Next byte sprite colorized + djnz lineLoop ;; [3] Decrement B (Width) if != 0 goto lineLoop + +nextLine: + dec c ;; [1] Decrement C (Height) + jr nz, convertLoop ;; [2/3] If != O goto convertLoop + +end: + ;; Return is included in bindings + diff --git a/examples/medium/colorReplace/src/asm/sprites/colorReplace/M0/cpct_spriteColorizeM0_asmbindings.s b/examples/medium/colorReplace/src/asm/sprites/colorReplace/M0/cpct_spriteColorizeM0_asmbindings.s new file mode 100644 index 000000000..9ac97a5e6 --- /dev/null +++ b/examples/medium/colorReplace/src/asm/sprites/colorReplace/M0/cpct_spriteColorizeM0_asmbindings.s @@ -0,0 +1,36 @@ +;;-----------------------------LICENSE NOTICE------------------------------------ +;; This file is part of CPCtelera: An Amstrad CPC Game Engine +;; Copyright (C) 2017 Arnaud Bouche (Arnaud6128) +;; Copyright (C) 2017 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) +;; +;; This program is free software: you can redistribute it and/or modify +;; it under the terms of the GNU Lesser General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU Lesser General Public License for more details. +;; +;; You should have received a copy of the GNU Lesser General Public License +;; along with this program. If not, see <http://www.gnu.org/licenses/>. +;;------------------------------------------------------------------------------- +.module cpct_sprites + +.include "../../../macros/cpct_undocumentedOpcodes.s" + +;; +;; ASM bindings for <cpct_spriteColorizeM0> +;; +cpct_spriteColorizeM0_asm:: ;; Assembly entry point + + ;; GET Parameters from the stack + ld (dms_restore_ix + 2), ix ;; [6] Save IX to restore it before returning + pop hl ;; [3] HL = Return Address + +.include /cpct_spriteColorizeM0.asm/ + +dms_restore_ix: + ld ix, #0000 ;; [4] Restore IX before returning + ret ;; [3] Return to caller \ No newline at end of file diff --git a/examples/medium/colorReplace/src/asm/sprites/colorReplace/M0/cpct_spriteColorizeM0_cbindings.s b/examples/medium/colorReplace/src/asm/sprites/colorReplace/M0/cpct_spriteColorizeM0_cbindings.s new file mode 100644 index 000000000..f31436707 --- /dev/null +++ b/examples/medium/colorReplace/src/asm/sprites/colorReplace/M0/cpct_spriteColorizeM0_cbindings.s @@ -0,0 +1,48 @@ +;;-----------------------------LICENSE NOTICE------------------------------------ +;; This file is part of CPCtelera: An Amstrad CPC Game Engine +;; Copyright (C) 2017 Arnaud Bouche +;; Copyright (C) 2017 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) +;; +;; This program is free software: you can redistribute it and/or modify +;; it under the terms of the GNU Lesser General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU Lesser General Public License for more details. +;; +;; You should have received a copy of the GNU Lesser General Public License +;; along with this program. If not, see <http://www.gnu.org/licenses/>. +;;------------------------------------------------------------------------------- +.module cpct_sprites + +.include "../../../macros/cpct_undocumentedOpcodes.s" + +;; +;; C bindings for <cpct_spriteColorizeM0> +;; +;; 33 us, 14 bytes +;; +_cpct_spriteColorizeM0:: + + ;; GET Parameters from the stack + ld (dms_restore_ix + 2), ix ;; [6] Save IX to restore it before returning + pop hl ;; [3] HL = Return Address + + exx + pop hl ;; [3] HL' = Source address (Sprite) + pop de ;; [3] DE' = Destination Sprite color + pop bc ;; [5] BC' = (B = Sprite Height, C = Width) + exx + + ex (sp), hl ;; [6] HL = (H = newColor, L = oldColor) + ;; ... and leave Return Address at (SP) as we don't need to restore + ;; ... stack status because callin convention is __z88dk_callee + +.include /cpct_spriteColorizeM0.asm/ + +dms_restore_ix: + ld ix, #0000 ;; [4] Restore IX before returning + ret ;; [3] Return to caller \ No newline at end of file diff --git a/examples/medium/colorReplace/src/asm/sprites/colorReplace/M0/cpct_spriteMaskedColorizeM0.asm b/examples/medium/colorReplace/src/asm/sprites/colorReplace/M0/cpct_spriteMaskedColorizeM0.asm new file mode 100644 index 000000000..1f6101790 --- /dev/null +++ b/examples/medium/colorReplace/src/asm/sprites/colorReplace/M0/cpct_spriteMaskedColorizeM0.asm @@ -0,0 +1,175 @@ +;;-----------------------------LICENSE NOTICE------------------------------------ +;; This file is part of CPCtelera: An Amstrad CPC Game Engine +;; Copyright (C) 2017 Arnaud Bouche (Arnaud6128) +;; Copyright (C) 2017 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) +;; +;; This program is free software: you can redistribute it and/or modify +;; it under the terms of the GNU Lesser General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU Lesser General Public License for more details. +;; +;; You should have received a copy of the GNU Lesser General Public License +;; along with this program. If not, see <http://www.gnu.org/licenses/>. +;;------------------------------------------------------------------------------- +.module cpct_sprites + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; +;; Function: cpct_spriteMaskedColorizeM0 +;; +;; Replace a color in a Masked sprite and copy to another or the same sprite. +;; +;; C Definition: +;; void <cpct_spriteMaskedColorizeM0> (void* *sprite*, void* *spriteColor*, <u8> *width*, <u8> *height*, <u8> *oldColor*, <u8> *newColor*) __z88dk_callee; +;; +;; Input Parameters (6 bytes): +;; (2B HL') sprite - Source Sprite Pointer (array of pixel data) +;; (2B DE') spriteColor - Destination Sprite Pointer (can be also the Source Sprite) (array of pixel data) +;; (1B C') height - Sprite Height in bytes (>0) +;; (1B B') width - Sprite Width in *bytes* (Beware, *not* in pixels!) +;; (1B L) oldColor - Color to replace +;; (1B H) newColor - New color +;; +;; Assembly call (Input parameters on registers): +;; > call cpct_spriteMaskedColorizeM0_asm +;; +;; Parameter Restrictions: +;; * *sprite* must be an array containing sprite's pixels data in screen pixel format +;; along with mask data. Each mask byte will contain enabled bits as those that should +;; be picked from the background (transparent) and disabled bits for those that will +;; be printed from sprite colour data. Each mask data byte must precede its associated +;; colour data byte. +;; Sprite must be rectangular and all bytes in the array must be consecutive pixels, +;; starting from top-left corner and going left-to-right, top-to-bottom down to the +;; bottom-right corner. Total amount of bytes in pixel array should be +;; 2 x *width* x *height* (mask data doubles array size). +;; * *spriteColor* must be an array containing the new sprite's pixels data with the new color. +;; Total amount of bytes in pixel array should be 2 x *width* x *height* (mask data doubles array size). +;; * *width* must be the width of the sprite *in bytes*. Always remember that the width must be +;; expressed in bytes and *not* in pixels. +;; The correspondence is mode 0 : 1 byte = 2 pixels +;; * *height* must be the height of the sprite in bytes, and must be greater than 0. +;; There is no practical upper limit to this value. Height of a sprite in +;; bytes and pixels is the same value, as bytes only group consecutive pixels in +;; the horizontal space. +;; * *oldColor* must be the index of color (0 to 15) to replace +;; * *newColor* must be the index of the new color (0 to 15) +;; +;; Known limitations: +;; * This function *will not work from ROM*, as it uses self-modifying code. +;; * This function requires the CPC firmware to be DISABLED. Otherwise, random crashes might happen due to side effects. +;; +;; Destroyed Register values: +;; AF, BC, DE, HL, BC', DE', HL', IX +;; +;; Required memory: +;; C-bindings - 87 bytes +;; ASM-bindings - 73 bytes +;; +;; Time Measures: +;; (start code) +;; Case | microSecs (us) | CPU Cycles +;; ---------------------------------------------------------------- +;; | 29 + (41 + 6W)H | 116 + (164 + 24W)H +;; ---------------------------------------------------------------- +;; W=2,H=16 | 2109 | 8436 +;; W=4,H=32 | 877 | 3508 +;; ---------------------------------------------------------------- +;; Asm saving | -16 | -64 +;; ---------------------------------------------------------------- +;; (end code) +;; W = *width* in bytes, H = *height* in bytes, HH = [(H-1)/8] +;; +;; Credits: +;; Original routine optimized by @Docent and discussed in CPCWiki : +;; http://www.cpcwiki.eu/forum/programming/cpctelera-colorize-sprite/ +;; +;; Thanks to all of them for their help and support. +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +.globl dc_mode0_ct + +;; Macro to convert Pixel to xAxC xBxD format +.macro convertPixel + ;; From cpct_px2byteM0 + ld bc, #dc_mode0_ct ;; [3] BC points to conversion table (dc_mode0_ct) + + ;; Compute BC += A + add c ;; [1] | C += A + ld c, a ;; [1] | + sub a ;; [1] A = 0 (preserving Carry Flag) + adc b ;; [1] | B += Carry + ld b, a ;; [1] | + + ;; A = *(BC + A) + ld a, (bc) ;; [2] A = Value stored at the table pointed by BC +.endm + + ;; Convert newColor to pixel format (E) + ld a, h ;; [1] A = H new color index + convertPixel ;; [10] | Convert into A + ld e, a ;; [1] | E = A new color : xAxC xBxD + + ;; Convert oldColor to pixel format (D) + ld a, l ;; [1] A = L old color index + convertPixel ;; [10] | Convert into A + ld d, a ;; [1] | D = A old color : xAxC xBxD + + ld c, #0x55 ;; [2] C = Mask to get pixel A : xAxC xBxD + exx ;; [1] Switch to Alternate registers + + ld__ixl_c ;; [1] IXL = C (Width) + ld c, b ;; [1] C = B (Height) + +convertLoop: + ld__b_ixl ;; [2] B = IXL (Sprite Width) + +lineLoop: + ld a, (hl) ;; [2] A = (HL) current Byte of sprite Mask + ld (de), a ;; [2] (DE) = A Copy of sprite Mask + inc hl ;; [2] Next byte sprite Color source + inc de ;; [2] Next byte sprite Color destination + ld a, (hl) ;; [2] A = (HL) current Byte of sprite Color + + exx ;; [1] Switch to Default registers + + ld l, a ;; [1] L = A current Byte of sprite : ABAB ABAB + and c ;; [2] A |= C (C = 0x55) : xBxB xBxB + + cp d ;; [1] Test if pixel (A) is the old colour to be replaced (D) + jr nz, readPixelA ;; [2/3] If not equal go to next pixel + ld a, e ;; [1] else A = new colour to set (E) + +;; Pixel Mode 0 = ABAB ABAB +readPixelA: + ld h, a ;; [1] H = A (current colorized sprite) : xBxB xBxB + ld a, l ;; [1] L = A current Byte of sprite : ABAB ABAB + rrca ;; [1] A (current byte of sprite) >> 1 : ABAB ABAB -> xABA BABA + and c ;; [2] A |= Mask (0x55) : xAxA xAxA + + cp d ;; [1] Test if pixel (A) is the old colour to be replaced (D) + jr nz, readPixelB ;; [2/3] If not equal go to next pixel + ld a, e ;; [1] else A = new colour to set (E) + +readPixelB: + rlca ;; [1] A = xAxA xAxA << 1 : AxAx AxAx + or h ;; [1] A |= H (xBxB xBxB) : ABAB ABAB + +setByte: + exx ;; [1] Switch to Alternate registers + + ld (de), a ;; [2] Update current sprite byte with pixels + inc hl ;; [2] Next byte sprite source + inc de ;; [2] Next byte sprite colorized + djnz lineLoop ;; [3] Decrement B (Width) if != 0 goto lineLoop + + dec c ;; [1] Decrement C (Height) + jr nz, convertLoop ;; [2/3] If C == O goto end + +end: + ;; Return is included in bindings \ No newline at end of file diff --git a/examples/medium/colorReplace/src/asm/sprites/colorReplace/M0/cpct_spriteMaskedColorizeM0_asmbindings.s b/examples/medium/colorReplace/src/asm/sprites/colorReplace/M0/cpct_spriteMaskedColorizeM0_asmbindings.s new file mode 100644 index 000000000..30440d708 --- /dev/null +++ b/examples/medium/colorReplace/src/asm/sprites/colorReplace/M0/cpct_spriteMaskedColorizeM0_asmbindings.s @@ -0,0 +1,36 @@ +;;-----------------------------LICENSE NOTICE------------------------------------ +;; This file is part of CPCtelera: An Amstrad CPC Game Engine +;; Copyright (C) 2017 Arnaud Bouche (Arnaud6128) +;; Copyright (C) 2017 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) +;; +;; This program is free software: you can redistribute it and/or modify +;; it under the terms of the GNU Lesser General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU Lesser General Public License for more details. +;; +;; You should have received a copy of the GNU Lesser General Public License +;; along with this program. If not, see <http://www.gnu.org/licenses/>. +;;------------------------------------------------------------------------------- +.module cpct_sprites + +.include "../../../macros/cpct_undocumentedOpcodes.s" + +;; +;; ASM bindings for <cpct_spriteMaskedColorizeM0> +;; +cpct_spriteMaskedColorizeM0_asm:: ;; Assembly entry point + + ;; GET Parameters from the stack + ld (dms_restore_ix + 2), ix ;; [6] Save IX to restore it before returning + pop hl ;; [3] HL = Return Address + +.include /cpct_spriteMaskedColorizeM0.asm/ + +dms_restore_ix: + ld ix, #0000 ;; [4] Restore IX before returning + ret ;; [3] Return to caller \ No newline at end of file diff --git a/examples/medium/colorReplace/src/asm/sprites/colorReplace/M0/cpct_spriteMaskedColorizeM0_cbindings.s b/examples/medium/colorReplace/src/asm/sprites/colorReplace/M0/cpct_spriteMaskedColorizeM0_cbindings.s new file mode 100644 index 000000000..a2bba9de5 --- /dev/null +++ b/examples/medium/colorReplace/src/asm/sprites/colorReplace/M0/cpct_spriteMaskedColorizeM0_cbindings.s @@ -0,0 +1,48 @@ +;;-----------------------------LICENSE NOTICE------------------------------------ +;; This file is part of CPCtelera: An Amstrad CPC Game Engine +;; Copyright (C) 2017 Arnaud Bouche (Arnaud6128) +;; Copyright (C) 2017 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) +;; +;; This program is free software: you can redistribute it and/or modify +;; it under the terms of the GNU Lesser General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU Lesser General Public License for more details. +;; +;; You should have received a copy of the GNU Lesser General Public License +;; along with this program. If not, see <http://www.gnu.org/licenses/>. +;;------------------------------------------------------------------------------- +.module cpct_sprites + +.include "../../../macros/cpct_undocumentedOpcodes.s" + +;; +;; C bindings for <cpct_spriteMaskedColorizeM0> +;; +;; 33 us, 14 bytes +;; +_cpct_spriteMaskedColorizeM0:: + + ;; GET Parameters from the stack + ld (dms_restore_ix + 2), ix ;; [6] Save IX to restore it before returning + pop hl ;; [3] HL = Return Address + + exx + pop hl ;; [3] HL' = Source address (Sprite) + pop de ;; [3] DE' = Destination Sprite color + pop bc ;; [5] BC' = (B = Sprite Height, C = Width) + exx + + ex (sp), hl ;; [6] HL = (H = newColor, L = oldColor) + ;; ... and leave Return Address at (SP) as we don't need to restore + ;; ... stack status because callin convention is __z88dk_callee + +.include /cpct_spriteMaskedColorizeM0.asm/ + +dms_restore_ix: + ld ix, #0000 ;; [4] Restore IX before returning + ret ;; [3] Return to caller \ No newline at end of file diff --git a/examples/medium/colorReplace/src/asm/sprites/colorReplace/M1/cpct_drawSpriteColorizeM1.asm b/examples/medium/colorReplace/src/asm/sprites/colorReplace/M1/cpct_drawSpriteColorizeM1.asm new file mode 100644 index 000000000..bcf3f88da --- /dev/null +++ b/examples/medium/colorReplace/src/asm/sprites/colorReplace/M1/cpct_drawSpriteColorizeM1.asm @@ -0,0 +1,228 @@ +;;-----------------------------LICENSE NOTICE------------------------------------ +;; This file is part of CPCtelera: An Amstrad CPC Game Engine +;; Copyright (C) 2017 Arnaud Bouche (Arnaud6128) +;; Copyright (C) 2017 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) +;; +;; This program is free software: you can redistribute it and/or modify +;; it under the terms of the GNU Lesser General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU Lesser General Public License for more details. +;; +;; You should have received a copy of the GNU Lesser General Public License +;; along with this program. If not, see <http://www.gnu.org/licenses/>. +;;------------------------------------------------------------------------------- +.module cpct_sprites + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; +;; Function: cpct_drawSpriteColorizeM1 +;; +;; Directly replace a color and draw a sprite to video memory. +;; +;; C Definition: +;; void <cpct_drawSpriteColorizeM1> (void* *sprite*, void* *memory*, <u8> *width*, <u8> *height*, <u8> *oldColor*, <u8> *newColor*) __z88dk_callee; +;; +;; Input Parameters (6 bytes): +;; (2B HL') sprite - Source Sprite Pointer (array of pixel data) +;; (2B DE') memory - Destination video memory pointer +;; (1B C' ) height - Sprite Height in bytes (>0) +;; (1B B' ) width - Sprite Width in *bytes* (Beware, *not* in pixels!) +;; (1B L ) oldColor - Color to replace +;; (1B H ) newColor - New color +;; +;; Assembly call (Input parameters on registers): +;; > call cpct_drawSpriteColorizeM1_asm +;; +;; Parameter Restrictions: +;; * *sprite* must be an array containing sprite's pixels data in screen pixel format. +;; Sprite must be rectangular and all bytes in the array must be consecutive pixels, +;; starting from top-left corner and going left-to-right, top-to-bottom down to the +;; bottom-right corner. Total amount of bytes in pixel array should be *width* x *height*. +;; * *memory* could be any place in memory, inside or outside current video memory. It +;; will be equally treated as video memory (taking into account CPC's video memory +;; disposition). This lets you copy sprites to software or hardware backbuffers, and +;; not only video memory. +;; * *width* must be the width of the sprite *in bytes*. Always remember that the width must be +;; expressed in bytes and *not* in pixels. +;; The correspondence is mode 1 : 1 byte = 4 pixels +;; * *height* must be the height of the sprite in bytes, and must be greater than 0. +;; There is no practical upper limit to this value. Height of a sprite in +;; bytes and pixels is the same value, as bytes only group consecutive pixels in +;; the horizontal space. +;; * *oldColor* must be the index of color (0 to 3) to replace +;; * *newColor* must be the index of the new color (0 to 3) +;; +;; Known limitations: +;; * This function does not do any kind of boundary check or clipping. If you +;; try to draw sprites on the frontier of your video memory or screen buffer +;; if might potentially overwrite memory locations beyond boundaries. This +;; could cause your program to behave erratically, hang or crash. Always +;; take the necessary steps to guarantee that you are drawing inside screen +;; or buffer boundaries. +;; * As this function receives a byte-pointer to memory, it can only +;; draw byte-sized and byte-aligned sprites. This means that the box cannot +;; start on non-byte aligned pixels (like odd-pixels, for instance) and +;; their sizes must be a multiple of a byte (2 in mode 0, 4 in mode 1 and +;; 8 in mode 2). +;; * This function *will not work from ROM*, as it uses self-modifying code. +;; * This function requires the CPC firmware to be DISABLED. Otherwise, random crashes might happen due to side effects. +;; +;; Destroyed Register values: +;; AF, BC, DE, HL, BC', DE', HL', IX +;; +;; Required memory: +;; C-bindings - 116 bytes +;; ASM-bindings - 103 bytes +;; +;; Time Measures: +;; (start code) +;; Case | microSecs (us) | CPU Cycles +;; ---------------------------------------------------------------- +;; | 29 + (36 + 61W)H | 116 + (144 + 244W)H +;; ---------------------------------------------------------------- +;; W=2,H=16 | 2557 | 10228 +;; W=4,H=32 | 8989 | 35956 +;; ---------------------------------------------------------------- +;; Asm saving | -16 | -64 +;; ---------------------------------------------------------------- +;; (end code) +;; W = *width* in bytes, H = *height* in bytes +;; +;; Credits: +;; Original routine optimized by @Docent and discussed in CPCWiki : +;; http://www.cpcwiki.eu/forum/programming/cpctelera-colorize-sprite/ +;; +;; Thanks to all of them for their help and support. +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +.globl dc_mode1_ct + +;; Macro to convert color to pixel Mode1 : Axxx Axxx +.macro convertPixel ;; From cpct_px2byteM1 + ld bc, #dc_mode1_ct ;; [3] BC points to conversion table (dc_mode1_ct) + + ;; Compute BC += A + add c ;; [1] | C += A + ld c, a ;; [1] | + sub a ;; [1] A = 0 (preserving Carry Flag) + adc b ;; [1] | B += Carry + ld b, a ;; [1] | + + ;; A = *(BC + A) + ld a, (bc) ;; [2] A = Value stored at the table pointed by BC +.endm + + ;; Convert newColor to pixel format (E) + ld a, h ;; [1] A = H new color index + convertPixel ;; [10] | Convert into A + ld e, a ;; [1] | E = A new color : Axxx Axxx + + ;; Convert oldColor to pixel format (D) + ld a, l ;; [1] A = L old color index + convertPixel ;; [10] | Convert into A + ld d, a ;; [1] | D = A old color : Axxx Axxx + + ld c, #0x88 ;; [2] C = Mask to get pixel A : Axxx Axxx + exx ;; [1] Switch to Alternate registers + + ld__ixl_c ;; [1] IXL = C (Width) + ld c, b ;; [1] C = B (Height) + +convertLoop: + ld (startLine), de ;; [6] Store DE start line (DestMem) + ld__b_ixl ;; [2] B = IXL (Sprite Width) + +lineLoop: + ld a, (hl) ;; [2] A = (HL) current Byte of sprite + exx ;; [1] Switch to Default registers + + ld l, a ;; [1] L = A current Byte of sprite : ABCD ABCD + and c ;; [2] A |= C (C = 0x88) : Axxx Axxx + + cp d ;; [1] Test if pixel (A) is the old colour to be replaced (D) + jr nz, readPixelA ;; [2/3] If not equal go to next pixel + ld a, e ;; [1] else A = new colour to set (E) + +readPixelA: + ld h, a ;; [1] H = A (current colorized sprite) : Axxx Axxx + + sla l ;; [2] L (current byte of sprite) << 1 : ABCD ABCD -> BCDx BCDx + ld a, l ;; [1] A = L : BCDx BCDx + and c ;; [2] A |= Mask (0x88) : Bxxx Bxxx + + cp d ;; [1] Test if pixel (A) is the old colour to be replaced (D) + jr nz, readPixelB ;; [2/3] If not equal go to next pixel + ld a, e ;; [1] else A = new colour to set (E) + +readPixelB: + rrca ;; [1] A = Axxx Axxx >> 1 : xBxx xBxx + or h ;; [1] A |= H (color byte) : Axxx Axxx + ld h, a ;; [1] H = A : ABxx ABxx + + sla l ;; [2] L ( BCDx BCDx) << 1 : CDxx CDxx + ld a, l ;; [1] A = L : CDxx CDxx + and c ;; [1] A |= C (C = 0x88) : Cxxx Cxxx + + cp d ;; [1] Test if pixel (A) is the old colour to be replaced (D) + jr nz, readPixelC ;; [2/3] If not equal go to next pixel + ld a, e ;; [1] else A = new colour to set (E) + +readPixelC: + rrca ;; [1] A = Axxx Axxx >> 1 : xBxx xBxx + rrca ;; [1] A = xxCx xxCx << 1 : xxCx xxCx + or h ;; [1] A |= H (ABxx ABxx) : ABCx ABCx + ld h, a ;; [1] H = A : ABCx ABCx + + sla l ;; [2] L (BCDx BCDx) << 1 : Dxxx Dxxx + ld a, l ;; [1] A = L : Dxxx Dxxx + and c ;; [1] A |= C (C = 0x88) : Dxxx Dxxx + + cp d ;; [1] Test if pixel (A) is the old colour to be replaced (D) + jr nz, readPixelD ;; [2/3] If not equal go to next pixel + ld a, e ;; [1] else A = new colour to set (E) + +readPixelD: + rrca ;; [1] A = Axxx Axxx >> 1 : xBxx xBxx + rrca ;; [1] A = xBxx xBxx >> 1 : xxCx xxCx + rrca ;; [1] A = xxCx xxxx >> 1 : xxxD xxxD + or h ;; [1] A |= H (ABCx ABCx) : ABCD ABCD + + exx ;; [1] Switch to Alternate registers + + ld (de), a ;; [2] Update current sprite byte with pixels + inc hl ;; [2] Next byte sprite source + inc de ;; [2] Next byte sprite colorized + djnz lineLoop ;; [3] Decrement B (Width) if B != 0 goto lineLoop + + dec c ;; [1] Decrement C (Height) + jr z, end ;; [2/3] If C == O goto end + +startLine = .+1 ;; Placeholder for the Start line adress + ld de, #0000 ;; [3] DE = Start Line + + ld a, d ;; [1] Start of next pixel line normally is 0x0800 bytes away. + add #0x08 ;; [2] so we add it to DE (just by adding 0x08 to D) + ld d, a ;; [1] + and #0x38 ;; [2] We check if we have crossed memory boundary (every 8 pixel lines).. + + jr nz, convertLoop ;; [2/3] .. by checking the 4 bits that identify present memory line. + ;; .... If 0, we have crossed boundaries + +dms_sprite_8bit_boundary_crossed: + ld a, e ;; [1] DE = DE + 0xC050h + add #0x50 ;; [2] -- Relocate DE pointer to the start of the next pixel line: + ld e, a ;; [1] -- DE is moved forward 3 memory banks plus 50 bytes (4000h * 3) + ld a, d ;; [1] -- which effectively is the same as moving it 1 bank backwards and then + adc #0xC0 ;; [2] -- 50 bytes forwards (which is what we want to move it to the next pixel line) + ld d, a ;; [1] -- Calculations are made with 8 bit maths as it is faster than other alternatives here + + jr convertLoop ;; [3] Jump to continue with next pixel line + +end: + ;; Return is included in bindings + diff --git a/examples/medium/colorReplace/src/asm/sprites/colorReplace/M1/cpct_drawSpriteColorizeM1_asmbindings.s b/examples/medium/colorReplace/src/asm/sprites/colorReplace/M1/cpct_drawSpriteColorizeM1_asmbindings.s new file mode 100644 index 000000000..44ca0f2b0 --- /dev/null +++ b/examples/medium/colorReplace/src/asm/sprites/colorReplace/M1/cpct_drawSpriteColorizeM1_asmbindings.s @@ -0,0 +1,35 @@ +;;-----------------------------LICENSE NOTICE------------------------------------ +;; This file is part of CPCtelera: An Amstrad CPC Game Engine +;; Copyright (C) 2017 Arnaud Bouche (Arnaud6128) +;; Copyright (C) 2017 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) +;; +;; This program is free software: you can redistribute it and/or modify +;; it under the terms of the GNU Lesser General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU Lesser General Public License for more details. +;; +;; You should have received a copy of the GNU Lesser General Public License +;; along with this program. If not, see <http://www.gnu.org/licenses/>. +;;------------------------------------------------------------------------------- +.module cpct_sprites + +.include "../../../macros/cpct_undocumentedOpcodes.s" + +;; +;; ASM bindings for <cpct_drawSpriteColorizeM1> +;; +cpct_drawSpriteColorizeM1_asm:: ;; Assembly entry point + +;; GET Parameters from the stack +ld (dms_restore_ix + 2), ix ;; [6] Save IX to restore it before returning + +.include /cpct_drawSpriteColorizeM1.asm/ + +dms_restore_ix: + ld ix, #0000 ;; [4] Restore IX before returning + ret \ No newline at end of file diff --git a/examples/medium/colorReplace/src/asm/sprites/colorReplace/M1/cpct_drawSpriteColorizeM1_cbindings.s b/examples/medium/colorReplace/src/asm/sprites/colorReplace/M1/cpct_drawSpriteColorizeM1_cbindings.s new file mode 100644 index 000000000..22798d0f3 --- /dev/null +++ b/examples/medium/colorReplace/src/asm/sprites/colorReplace/M1/cpct_drawSpriteColorizeM1_cbindings.s @@ -0,0 +1,48 @@ +;;-----------------------------LICENSE NOTICE------------------------------------ +;; This file is part of CPCtelera: An Amstrad CPC Game Engine +;; Copyright (C) 2017 Arnaud Bouche (Arnaud6128) +;; Copyright (C) 2017 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) +;; +;; This program is free software: you can redistribute it and/or modify +;; it under the terms of the GNU Lesser General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU Lesser General Public License for more details. +;; +;; You should have received a copy of the GNU Lesser General Public License +;; along with this program. If not, see <http://www.gnu.org/licenses/>. +;;------------------------------------------------------------------------------- +.module cpct_sprites + +.include "../../../macros/cpct_undocumentedOpcodes.s" + +;; +;; C bindings for <cpct_drawSpriteColorizeM1> +;; +;; 31 us, 13 bytes +;; +_cpct_drawSpriteColorizeM1:: + + ;; GET Parameters from the stack + ld (dms_restore_ix + 2), ix ;; [6] Save IX to restore it before returning + pop hl ;; [3] HL = Return Address + + exx + pop hl ;; [3] HL' = Source address (Sprite) + pop de ;; [3] DE' = Destination Memory + pop bc ;; [5] BC' = (B = Sprite Height, C = Width) + exx + + ex (sp), hl ;; [6] HL = (H = newColor, L = oldColor) + ;; ... and leave Return Address at (SP) as we don't need to restore + ;; ... stack status because callin convention is __z88dk_callee + +.include /cpct_drawSpriteColorizeM1.asm/ + +dms_restore_ix: + ld ix, #0000 ;; [4] Restore IX before returning + ret ;; [3] Return to caller \ No newline at end of file diff --git a/examples/medium/colorReplace/src/asm/sprites/colorReplace/M1/cpct_drawSpriteMaskedAlignedColorizeM1.asm b/examples/medium/colorReplace/src/asm/sprites/colorReplace/M1/cpct_drawSpriteMaskedAlignedColorizeM1.asm new file mode 100644 index 000000000..6d2cda5ee --- /dev/null +++ b/examples/medium/colorReplace/src/asm/sprites/colorReplace/M1/cpct_drawSpriteMaskedAlignedColorizeM1.asm @@ -0,0 +1,239 @@ +;;-----------------------------LICENSE NOTICE------------------------------------ +;; This file is part of CPCtelera: An Amstrad CPC Game Engine +;; Copyright (C) 2017 Arnaud Bouche (Arnaud6128) +;; Copyright (C) 2017 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) +;; +;; This program is free software: you can redistribute it and/or modify +;; it under the terms of the GNU Lesser General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU Lesser General Public License for more details. +;; +;; You should have received a copy of the GNU Lesser General Public License +;; along with this program. If not, see <http://www.gnu.org/licenses/>. +;;------------------------------------------------------------------------------- +.module cpct_sprites + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; +;; Function: cpct_drawSpriteMaskedAlignedColorizeM1 +;; +;; Directly replace a color and draw a sprite Masked Aligned to video memory. +;; +;; C Definition: +;; void <cpct_drawSpriteMaskedAlignedColorizeM1> (void* *sprite*, void* *memory*, <u8> *width*, <u8> *height*, +;; <u8> *oldColor*, <u8> *newColor*, <u8*> *pmasktable*) __z88dk_callee; +;; +;; Input Parameters (10 bytes): +;; (2B HL') sprite - Source Sprite Pointer (array of pixel data) +;; (2B DE') memory - Destination video memory pointer +;; (1B C' ) height - Sprite Height in bytes (>0) +;; (1B B' ) width - Sprite Width in *bytes* (Beware, *not* in pixels!) +;; (1B E ) oldColor - Color to replace +;; (1B D ) newColor - New color +;; (2B HL) pmasktable - Pointer to the aligned mask table used to create transparency +;; +;; Assembly call (Input parameters on registers): +;; > call cpct_drawSpriteMaskedAlignedColorizeM1_asm +;; +;; Parameter Restrictions: +;; * *sprite* must be an array containing sprite's pixels data in screen pixel format +;; Sprite must be rectangular and all bytes in the array must be consecutive pixels, +;; starting from top-left corner and going left-to-right, top-to-bottom down to the +;; bottom-right corner. Total amount of bytes in pixel array should be *width* x *height*. +;; * *memory* could be any place in memory, inside or outside current video memory. It +;; will be equally treated as video memory (taking into account CPC's video memory +;; disposition). This lets you copy sprites to software or hardware backbuffers, and +;; not only video memory. +;; * *width* must be the width of the sprite *in bytes*. Always remember that the width must be +;; expressed in bytes and *not* in pixels. +;; The correspondence is mode 0 : 1 byte = 4 pixels +;; * *height* must be the height of the sprite in bytes, and must be greater than 0. +;; There is no practical upper limit to this value. Height of a sprite in +;; bytes and pixels is the same value, as bytes only group consecutive pixels in +;; the horizontal space. +;; * *oldColor* must be the index of color (0 to 3) to replace +;; * *newColor* must be the index of the new color (0 to 3) +;; +;; Known limitations: +;; * This function does not do any kind of boundary check or clipping. If you +;; try to draw sprites on the frontier of your video memory or screen buffer +;; if might potentially overwrite memory locations beyond boundaries. This +;; could cause your program to behave erratically, hang or crash. Always +;; take the necessary steps to guarantee that you are drawing inside screen +;; or buffer boundaries. +;; * As this function receives a byte-pointer to memory, it can only +;; draw byte-sized and byte-aligned sprites. This means that the box cannot +;; start on non-byte aligned pixels (like odd-pixels, for instance) and +;; their sizes must be a multiple of a byte (2 in mode 0, 4 in mode 1 and +;; 8 in mode 2). +;; * This function *will not work from ROM*, as it uses self-modifying code. +;; * This function requires the CPC firmware to be DISABLED. Otherwise, random crashes might happen due to side effects. +;; +;; Destroyed Register values: +;; AF, BC, DE, HL, BC', DE', HL', IX +;; +;; Required memory: +;; C-bindings - 133 bytes +;; ASM-bindings - 117 bytes +;; +;; Time Measures: +;; (start code) +;; Case | microSecs (us) | CPU Cycles +;; ---------------------------------------------------------------- +;; | 32 + (33 + 75W)H | 128 + (132 + 300W)H +;; ---------------------------------------------------------------- +;; W=2,H=16 | 2960 | 11840 +;; W=4,H=32 | 10688 | 42752 +;; ---------------------------------------------------------------- +;; Asm saving | -16 | -64 +;; ---------------------------------------------------------------- +;; (end code) +;; W = *width* in bytes, H = *height* in bytes, HH = [(H-1)/8] +;; +;; Credits: +;; Original routine optimized by @Docent and discussed in CPCWiki : +;; http://www.cpcwiki.eu/forum/programming/cpctelera-colorize-sprite/ +;; +;; Thanks to all of them for their help and support. +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +.globl dc_mode1_ct + +;; Macro to convert color to pixel Mode1 : Axxx Axxx +.macro convertPixel ;; From cpct_px2byteM1 + ld bc, #dc_mode1_ct ;; [3] BC points to conversion table (dc_mode1_ct) + + ;; Compute BC += A + add c ;; [1] | C += A + ld c, a ;; [1] | + sub a ;; [1] A = 0 (preserving Carry Flag) + adc b ;; [1] | B += Carry + ld b, a ;; [1] | + + ;; A = *(BC + A) + ld a, (bc) ;; [2] A = Value stored at the table pointed by HL +.endm + + ;; Convert newColor to pixel format (E) + ld a, h ;; [1] A = H new color index + convertPixel ;; [10] | Convert into A + ld e, a ;; [1] | E = A new color : Axxx Axxx + + ;; Convert oldColor to pixel format (D) + ld a, l ;; [1] A = L old color index + convertPixel ;; [10] | Convert into A + ld d, a ;; [1] | D = A old color : Axxx Axxx + + ld c, #0x88 ;; [2] C = Mask to get pixel A : Axxx Axxx + exx ;; [1] Switch to Alternate registers + + ld__ixl_c ;; [1] IXL = C (Width) + ld c, b ;; [1] C = B (Height) + +convertLoop: + push de ;; [4] Store DE start line (DestMem) + ld__b_ixl ;; [2] B = IXL (Sprite Width) + +lineLoop: + ld a, (hl) ;; [2] A = (HL) current Byte of sprite Mask + exx ;; [1] Switch to Default registers + + ld l, a ;; [1] L = A current Byte of sprite : ABCD ABCD + and c ;; [2] A |= C (C = 0x88) : Axxx Axxx + + cp d ;; [1] Test if pixel (A) is the old colour to be replaced (D) + jr nz, readPixelA ;; [2/3] If not equal go to next pixel + ld a, e ;; [1] else A = new colour to set (E) + +readPixelA: + ld h, a ;; [1] H = A (current colorized sprite) : Axxx Axxx + + sla l ;; [2] L (current byte of sprite) << 1 : ABCD ABCD -> BCDx BCDx + ld a, l ;; [1] A = L : BCDx BCDx + and c ;; [2] A |= Mask (0x88) : Bxxx Bxxx + + cp d ;; [1] Test if pixel (A) is the old colour to be replaced (D) + jr nz, readPixelB ;; [2/3] If not equal go to next pixel + ld a, e ;; [1] else A = new colour to set (E) + +readPixelB: + rrca ;; [1] A = Axxx Axxx >> 1 : xBxx xBxx + or h ;; [1] A |= H (color byte) : Axxx Axxx + ld h, a ;; [1] H = A : ABxx ABxx + + sla l ;; [2] L ( BCDx BCDx) << 1 : CDxx CDxx + ld a, l ;; [1] A = L : CDxx CDxx + and c ;; [1] A |= C (C = 0x88) : Cxxx Cxxx + + cp d ;; [1] Test if pixel (A) is the old colour to be replaced (D) + jr nz, readPixelC ;; [2/3] If not equal go to next pixel + ld a, e ;; [1] else A = new colour to set (E) + +readPixelC: + rrca ;; [1] A = Axxx Axxx >> 1 : xBxx xBxx + rrca ;; [1] A = xxCx xxCx << 1 : xxCx xxCx + or h ;; [1] A |= H (ABxx ABxx) : ABCx ABCx + ld h, a ;; [1] H = A : ABCx ABCx + + sla l ;; [2] L (BCDx BCDx) << 1 : Dxxx Dxxx + ld a, l ;; [1] A = L : Dxxx Dxxx + and c ;; [1] A |= C (C = 0x88) : Dxxx Dxxx + + cp d ;; [1] Test if pixel (A) is the old colour to be replaced (D) + jr nz, readPixelD ;; [2/3] If not equal go to next pixel + ld a, e ;; [1] else A = new colour to set (E) + +readPixelD: + rrca ;; [1] A = Axxx Axxx >> 1 : xBxx xBxx + rrca ;; [1] A = xBxx xBxx >> 1 : xxCx xxCx + rrca ;; [1] A = xxCx xxxx >> 1 : xxxD xxxD + or h ;; [1] A |= H (ABCx ABCx) : ABCD ABCD + + exx ;; [1] Switch to Alternate registers + +drawByte: + push hl ;; [4] Store HL (current byte sprite source) + ld h, b ;; [1] H = B (Masked table adress High Byte) + ld l, a ;; [1] Access mask table element (table must be 256-byte aligned) + ld a, (de) ;; [2] Get the value of the byte of the screen where we are going to draw + and (hl) ;; [2] Erase background part that is to be overwritten (Mask step 1) + or l ;; [1] Add up background and sprite information in one byte (Mask step 2) + ld (de), a ;; [2] Save modified background + sprite data information into memory + pop hl ;; [3] Recover HL (current byte sprite source) + + inc hl ;; [2] Next byte sprite source + inc de ;; [2] Next byte sprite colorized + djnz lineLoop ;; [3] Decrement B (Width) if B != 0 goto lineLoop + + dec c ;; [1] Decrement C (Height) + jr z, end ;; [2/3] If C == O goto end + + pop de ;; [3] Restore DE start line (DestMem + + ld a, d ;; [1] Start of next pixel line normally is 0x0800 bytes away. + add #0x08 ;; [2] so we add it to DE (just by adding 0x08 to D) + ld d, a ;; [1] + and #0x38 ;; [2] We check if we have crossed memory boundary (every 8 pixel lines).. + + jr nz, convertLoop ;; [2/3] .. by checking the 4 bits that identify present memory line. + ;; .... If 0, we have crossed boundaries + +dms_sprite_8bit_boundary_crossed: + ld a, e ;; [1] DE = DE + 0xC050h + add #0x50 ;; [2] -- Relocate DE pointer to the start of the next pixel line: + ld e, a ;; [1] -- DE is moved forward 3 memory banks plus 50 bytes (4000h * 3) + ld a, d ;; [1] -- which effectively is the same as moving it 1 bank backwards and then + adc #0xC0 ;; [2] -- 50 bytes forwards (which is what we want to move it to the next pixel line) + ld d, a ;; [1] -- Calculations are made with 8 bit maths as it is faster than other alternatives here + + jr convertLoop ;; [3] Jump to continue with next pixel line + +end: + pop de ;; [3] Empty stack by getting last element (DestMem) + ;; Return is included in bindings + diff --git a/examples/medium/colorReplace/src/asm/sprites/colorReplace/M1/cpct_drawSpriteMaskedAlignedColorizeM1_asmbindings.s b/examples/medium/colorReplace/src/asm/sprites/colorReplace/M1/cpct_drawSpriteMaskedAlignedColorizeM1_asmbindings.s new file mode 100644 index 000000000..db02086d7 --- /dev/null +++ b/examples/medium/colorReplace/src/asm/sprites/colorReplace/M1/cpct_drawSpriteMaskedAlignedColorizeM1_asmbindings.s @@ -0,0 +1,36 @@ +;;-----------------------------LICENSE NOTICE------------------------------------ +;; This file is part of CPCtelera: An Amstrad CPC Game Engine +;; Copyright (C) 2017 Arnaud Bouche (Arnaud6128) +;; Copyright (C) 2017 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) +;; +;; This program is free software: you can redistribute it and/or modify +;; it under the terms of the GNU Lesser General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU Lesser General Public License for more details. +;; +;; You should have received a copy of the GNU Lesser General Public License +;; along with this program. If not, see <http://www.gnu.org/licenses/>. +;;------------------------------------------------------------------------------- +.module cpct_sprites + +.include "../../../macros/cpct_undocumentedOpcodes.s" + +;; +;; ASM bindings for <cpct_drawSpriteMaskedAlignedColorizeM1> +;; +cpct_drawSpriteMaskedAlignedColorizeM1_asm:: ;; Assembly entry point + + ;; GET Parameters from the stack + ld (dms_restore_ix + 2), ix ;; [6] Save IX to restore it before returning + pop hl ;; [3] HL = Return Address + +.include /cpct_drawSpriteMaskedAlignedColorizeM1.asm/ + +dms_restore_ix: + ld ix, #0000 ;; [4] Restore IX before returning + ret ;; [3] Return to caller \ No newline at end of file diff --git a/examples/medium/colorReplace/src/asm/sprites/colorReplace/M1/cpct_drawSpriteMaskedAlignedColorizeM1_cbindings.s b/examples/medium/colorReplace/src/asm/sprites/colorReplace/M1/cpct_drawSpriteMaskedAlignedColorizeM1_cbindings.s new file mode 100644 index 000000000..f0b0a2130 --- /dev/null +++ b/examples/medium/colorReplace/src/asm/sprites/colorReplace/M1/cpct_drawSpriteMaskedAlignedColorizeM1_cbindings.s @@ -0,0 +1,53 @@ +;;-----------------------------LICENSE NOTICE------------------------------------ +;; This file is part of CPCtelera: An Amstrad CPC Game Engine +;; Copyright (C) 2017 Arnaud Bouche (Arnaud6128) +;; Copyright (C) 2017 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) +;; +;; This program is free software: you can redistribute it and/or modify +;; it under the terms of the GNU Lesser General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU Lesser General Public License for more details. +;; +;; You should have received a copy of the GNU Lesser General Public License +;; along with this program. If not, see <http://www.gnu.org/licenses/>. +;;------------------------------------------------------------------------------- +.module cpct_sprites + +.include "../../../macros/cpct_undocumentedOpcodes.s" + +;; +;; C bindings for <cpct_drawSpriteMaskedAlignedColorizeM1> +;; +;; 39 us, 16 bytes +;; +_cpct_drawSpriteMaskedAlignedColorizeM1:: + + ;; GET Parameters from the stack + ld (dms_restore_ix + 2), ix ;; [6] Save IX to restore it before returning + pop hl ;; [3] HL = Return Address + + exx ;; [1] Switch to Alternate registers + pop hl ;; [3] HL' = Source address (Sprite) + pop de ;; [3] DE' = Destination Memory + pop bc ;; [5] BC' = (B = Sprite Height, C = Width) + + exx ;; [1] Switch to Default registers + pop de ;; [3] DE = (D = newColor, E = oldColor) + + ex (sp), hl ;; [6] HL = Table Mask address + ;; ... and leave Return Address at (SP) as we don't need to restore + ;; ... stack status because callin convention is __z88dk_callee + + ex de, hl ;; [1] HL <-> DE + + +.include /cpct_drawSpriteMaskedAlignedColorizeM1.asm/ + +dms_restore_ix: + ld ix, #0000 ;; [4] Restore IX before returning + ret ;; [3] Return to caller \ No newline at end of file diff --git a/examples/medium/colorReplace/src/asm/sprites/colorReplace/M1/cpct_drawSpriteMaskedColorizeM1.asm b/examples/medium/colorReplace/src/asm/sprites/colorReplace/M1/cpct_drawSpriteMaskedColorizeM1.asm new file mode 100644 index 000000000..c96a67928 --- /dev/null +++ b/examples/medium/colorReplace/src/asm/sprites/colorReplace/M1/cpct_drawSpriteMaskedColorizeM1.asm @@ -0,0 +1,246 @@ +;;-----------------------------LICENSE NOTICE------------------------------------ +;; This file is part of CPCtelera: An Amstrad CPC Game Engine +;; Copyright (C) 2017 Arnaud Bouche (Arnaud6128) +;; Copyright (C) 2017 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) +;; +;; This program is free software: you can redistribute it and/or modify +;; it under the terms of the GNU Lesser General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU Lesser General Public License for more details. +;; +;; You should have received a copy of the GNU Lesser General Public License +;; along with this program. If not, see <http://www.gnu.org/licenses/>. +;;------------------------------------------------------------------------------- +.module cpct_sprites + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; +;; Function: cpct_drawSpriteMaskedColorizeM1 +;; +;; Directly replace a color and draw a sprite Masked to video memory. +;; +;; C Definition: +;; void <cpct_drawSpriteMaskedColorizeM1> (void* *sprite*, void* *memory*, <u8> *width*, <u8> *height*, <u8> *oldColor*, <u8> *newColor*) __z88dk_callee; +;; +;; Input Parameters (8 bytes): +;; (2B HL') sprite - Source Sprite Pointer (array of pixel data) +;; (2B DE') memory - Destination video memory pointer +;; (1B C' ) height - Sprite Height in bytes (>0) +;; (1B B' ) width - Sprite Width in *bytes* (Beware, *not* in pixels!) +;; (1B L ) oldColor - Color to replace +;; (1B H ) newColor - New color +;; +;; Assembly call (Input parameters on registers): +;; > call cpct_drawSpriteMaskedColorizeM1_asm +;; +;; Parameter Restrictions: +;; * *sprite* must be an array containing sprite's pixels data in screen pixel format +;; along with mask data. Each mask byte will contain enabled bits as those that should +;; be picked from the background (transparent) and disabled bits for those that will +;; be printed from sprite colour data. Each mask data byte must precede its associated +;; colour data byte. +;; Sprite must be rectangular and all bytes in the array must be consecutive pixels, +;; starting from top-left corner and going left-to-right, top-to-bottom down to the +;; bottom-right corner. Total amount of bytes in pixel array should be +;; 2 x *width* x *height* (mask data doubles array size). +;; * *memory* could be any place in memory, inside or outside current video memory. It +;; will be equally treated as video memory (taking into account CPC's video memory +;; disposition). This lets you copy sprites to software or hardware backbuffers, and +;; not only video memory. +;; * *width* must be the width of the sprite *in bytes*. Always remember that the width must be +;; expressed in bytes and *not* in pixels. +;; The correspondence is mode 0 : 1 byte = 4 pixels +;; * *height* must be the height of the sprite in bytes, and must be greater than 0. +;; There is no practical upper limit to this value. Height of a sprite in +;; bytes and pixels is the same value, as bytes only group consecutive pixels in +;; the horizontal space. +;; * *oldColor* must be the index of color (0 to 3) to replace +;; * *newColor* must be the index of the new color (0 to 3) +;; +;; Known limitations: +;; * This function does not do any kind of boundary check or clipping. If you +;; try to draw sprites on the frontier of your video memory or screen buffer +;; if might potentially overwrite memory locations beyond boundaries. This +;; could cause your program to behave erratically, hang or crash. Always +;; take the necessary steps to guarantee that you are drawing inside screen +;; or buffer boundaries. +;; * As this function receives a byte-pointer to memory, it can only +;; draw byte-sized and byte-aligned sprites. This means that the box cannot +;; start on non-byte aligned pixels (like odd-pixels, for instance) and +;; their sizes must be a multiple of a byte (2 in mode 0, 4 in mode 1 and +;; 8 in mode 2). +;; * This function *will not work from ROM*, as it uses self-modifying code. +;; * This function requires the CPC firmware to be DISABLED. Otherwise, random crashes might happen due to side effects. +;; +;; Destroyed Register values: +;; AF, BC, DE, HL, BC', DE', HL', IX +;; +;; Required memory: +;; C-bindings - 142 bytes +;; ASM-bindings - 129 bytes +;; +;; Time Measures: +;; (start code) +;; Case | microSecs (us) | CPU Cycles +;; ---------------------------------------------------------------- +;; | 29 + (36 + 93W)H | 116 + (144 + 372W)H +;; ---------------------------------------------------------------- +;; W=2,H=16 | 3581 | 14324 +;; W=4,H=32 | 13085 | 52340 +;; ---------------------------------------------------------------- +;; Asm saving | -16 | -64 +;; ---------------------------------------------------------------- +;; (end code) +;; W = *width* in bytes, H = *height* in bytes +;; +;; Credits: +;; Original routine optimized by @Docent and discussed in CPCWiki : +;; http://www.cpcwiki.eu/forum/programming/cpctelera-colorize-sprite/ +;; +;; Thanks to all of them for their help and support. +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +.globl dc_mode1_ct + +;; Macro to convert color to pixel Mode1 : Axxx Axxx +.macro convertPixel ;; From cpct_px2byteM1 + ld bc, #dc_mode1_ct ;; [3] BC points to conversion table (dc_mode1_ct) + + ;; Compute BC += A + add c ;; [1] | C += A + ld c, a ;; [1] | + sub a ;; [1] A = 0 (preserving Carry Flag) + adc b ;; [1] | B += Carry + ld b, a ;; [1] | + + ;; A = *(BC + A) + ld a, (bc) ;; [2] A = Value stored at the table pointed by BC +.endm + + ;; Convert newColor to pixel format (E) + ld a, h ;; [1] A = H new color index + convertPixel ;; [10] | Convert into A + ld e, a ;; [1] | E = A new color : Axxx Axxx + + ;; Convert oldColor to pixel format (D) + ld a, l ;; [1] A = L old color index + convertPixel ;; [10] | Convert into A + ld d, a ;; [1] | D = A old color : Axxx Axxx + + ld c, #0x88 ;; [2] C = First Mask to get pixel A : Axxx Axxx + exx ;; [1] Switch to Alternate registers + + ld__ixl_c ;; [1] IXL = C (Width) + ld c, b ;; [1] C = B (Height) + +convertLoop: + ld (startLine), de ;; [6] Store DE start line (DestMem) + ld__b_ixl ;; [2] B = IXL (Sprite Width) + +lineLoop: + inc hl ;; [2] Next byte sprite Color source + ld a, (hl) ;; [2] A = (HL) current Byte of sprite Color + dec hl ;; [2] Previous byte sprite Mask source + + exx ;; [1] Switch to Default registers + + ld l, a ;; [1] L = A current Byte of sprite : ABCD ABCD + + and c ;; [2] A |= C (C = 0x88) : Axxx Axxx + + cp d ;; [1] Test if pixel (A) is the old colour to be replaced (D) + jr nz, readPixelA ;; [2/3] If not equal go to next pixel + ld a, e ;; [1] else A = new colour to set (E) + +readPixelA: + ld h, a ;; [1] H = A (current colorized sprite) : Axxx Axxx + + sla l ;; [2] L (current byte of sprite) << 1 : ABCD ABCD -> BCDx BCDx + ld a, l ;; [1] A = L : BCDx BCDx + and c ;; [2] A |= Mask (0x88) : Bxxx Bxxx + + cp d ;; [1] Test if pixel (A) is the old colour to be replaced (D) + jr nz, readPixelB ;; [2/3] If not equal go to next pixel + ld a, e ;; [1] else A = new colour to set (E) + +readPixelB: + rrca ;; [1] A = Axxx Axxx >> 1 : xBxx xBxx + or h ;; [1] A |= H (color byte) : Axxx Axxx + ld h, a ;; [1] H = A : ABxx ABxx + + sla l ;; [2] L ( BCDx BCDx) << 1 : CDxx CDxx + ld a, l ;; [1] A = L : CDxx CDxx + and c ;; [1] A |= C (C = 0x88) : Cxxx Cxxx + + cp d ;; [1] Test if pixel (A) is the old colour to be replaced (D) + jr nz, readPixelC ;; [2/3] If not equal go to next pixel + ld a, e ;; [1] else A = new colour to set (E) + +readPixelC: + rrca ;; [1] A = Axxx Axxx >> 1 : xBxx xBxx + rrca ;; [1] A = xxCx xxCx << 1 : xxCx xxCx + or h ;; [1] A |= H (ABxx ABxx) : ABCx ABCx + ld h, a ;; [1] H = A : ABCx ABCx + + sla l ;; [2] L (BCDx BCDx) << 1 : Dxxx Dxxx + ld a, l ;; [1] A = L : Dxxx Dxxx + and c ;; [1] A |= C (C = 0x88) : Dxxx Dxxx + + cp d ;; [1] Test if pixel (A) is the old colour to be replaced (D) + jr nz, readPixelD ;; [2/3] If not equal go to next pixel + ld a, e ;; [1] else A = new colour to set (E) + +readPixelD: + rrca ;; [1] A = Axxx Axxx >> 1 : xBxx xBxx + rrca ;; [1] A = xBxx xBxx >> 1 : xxCx xxCx + rrca ;; [1] A = xxCx xxxx >> 1 : xxxD xxxD + or h ;; [1] A |= H (ABCx ABCx) : ABCD ABCD + + exx ;; [1] Switch to Alternate registers + +drawByte: + ld (sprite_color), a ;; [4] sprite_color = A (Sprite Byte) + + ld a, (de) ;; [2] Get next background byte into A + and (hl) ;; [2] Erase background part that is to be overwritten (Mask step 1) + inc hl ;; [3] HL += 1 => Point HL to Sprite Colour information +sprite_color = .+1 ;; Placeholder for the Sprite Color computed + or #00 ;; [2] Add up background and sprite information in one byte (Mask step 2) + ld (de), a ;; [2] Save modified background + sprite data information into memory + + inc hl ;; [2] Next byte sprite source + inc de ;; [2] Next byte Dest Memory + djnz lineLoop ;; [3] Decrement B (Width) if B != 0 goto lineLoop + + dec c ;; [1] Decrement C (Height) + jr z, end ;; [2/3] If C == O goto end + +startLine = .+1 ;; Placeholder for the Start line adress + ld de, #0000 ;; [3] DE = Start Line + + ld a, d ;; [1] Start of next pixel line normally is 0x0800 bytes away. + add #0x08 ;; [2] so we add it to DE (just by adding 0x08 to D) + ld d, a ;; [1] + and #0x38 ;; [2] We check if we have crossed memory boundary (every 8 pixel lines).. + + jr nz, convertLoop ;; [2/3] .. by checking the 4 bits that identify present memory line. + ;; .... If 0, we have crossed boundaries + +dms_sprite_8bit_boundary_crossed: + ld a, e ;; [1] DE = DE + 0xC050h + add #0x50 ;; [2] -- Relocate DE pointer to the start of the next pixel line: + ld e, a ;; [1] -- DE is moved forward 3 memory banks plus 50 bytes (4000h * 3) + ld a, d ;; [1] -- which effectively is the same as moving it 1 bank backwards and then + adc #0xC0 ;; [2] -- 50 bytes forwards (which is what we want to move it to the next pixel line) + ld d, a ;; [1] -- Calculations are made with 8 bit maths as it is faster than other alternatives here + + jr convertLoop ;; [3] Jump to continue with next pixel line + +end: + ;; Return is included in bindings + diff --git a/examples/medium/colorReplace/src/asm/sprites/colorReplace/M1/cpct_drawSpriteMaskedColorizeM1_asmbindings.s b/examples/medium/colorReplace/src/asm/sprites/colorReplace/M1/cpct_drawSpriteMaskedColorizeM1_asmbindings.s new file mode 100644 index 000000000..b2ed10933 --- /dev/null +++ b/examples/medium/colorReplace/src/asm/sprites/colorReplace/M1/cpct_drawSpriteMaskedColorizeM1_asmbindings.s @@ -0,0 +1,36 @@ +;;-----------------------------LICENSE NOTICE------------------------------------ +;; This file is part of CPCtelera: An Amstrad CPC Game Engine +;; Copyright (C) 2017 Arnaud Bouche (Arnaud6128) +;; Copyright (C) 2017 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) +;; +;; This program is free software: you can redistribute it and/or modify +;; it under the terms of the GNU Lesser General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU Lesser General Public License for more details. +;; +;; You should have received a copy of the GNU Lesser General Public License +;; along with this program. If not, see <http://www.gnu.org/licenses/>. +;;------------------------------------------------------------------------------- +.module cpct_sprites + +.include "../../../macros/cpct_undocumentedOpcodes.s" + +;; +;; ASM bindings for <cpct_drawSpriteMaskedColorizeM1> +;; +cpct_drawSpriteMaskedColorizeM1_asm:: ;; Assembly entry point + + ;; GET Parameters from the stack + ld (dms_restore_ix + 2), ix ;; [6] Save IX to restore it before returning + pop hl ;; [3] HL = Return Address + +.include /cpct_drawSpriteMaskedColorizeM1.asm/ + +dms_restore_ix: + ld ix, #0000 ;; [4] Restore IX before returning + ret ;; [3] Return to caller \ No newline at end of file diff --git a/examples/medium/colorReplace/src/asm/sprites/colorReplace/M1/cpct_drawSpriteMaskedColorizeM1_cbindings.s b/examples/medium/colorReplace/src/asm/sprites/colorReplace/M1/cpct_drawSpriteMaskedColorizeM1_cbindings.s new file mode 100644 index 000000000..aa21c471c --- /dev/null +++ b/examples/medium/colorReplace/src/asm/sprites/colorReplace/M1/cpct_drawSpriteMaskedColorizeM1_cbindings.s @@ -0,0 +1,48 @@ +;;-----------------------------LICENSE NOTICE------------------------------------ +;; This file is part of CPCtelera: An Amstrad CPC Game Engine +;; Copyright (C) 2017 Arnaud Bouche (Arnaud6128) +;; Copyright (C) 2017 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) +;; +;; This program is free software: you can redistribute it and/or modify +;; it under the terms of the GNU Lesser General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU Lesser General Public License for more details. +;; +;; You should have received a copy of the GNU Lesser General Public License +;; along with this program. If not, see <http://www.gnu.org/licenses/>. +;;------------------------------------------------------------------------------- +.module cpct_sprites + +.include "../../../macros/cpct_undocumentedOpcodes.s" + +;; +;; C bindings for <cpct_drawSpriteMaskedColorizeM1> +;; +;; 33 us, 13 bytes +;; +_cpct_drawSpriteMaskedColorizeM1:: + + ;; GET Parameters from the stack + ld (dms_restore_ix + 2), ix ;; [6] Save IX to restore it before returning + pop hl ;; [3] HL = Return Address + + exx + pop hl ;; [3] HL' = Source address (Sprite) + pop de ;; [3] DE' = Destination Memory + pop bc ;; [5] BC' = (B = Sprite Height, C = Width) + exx + + ex (sp), hl ;; [6] HL = (H = newColor, L = oldColor) + ;; ... and leave Return Address at (SP) as we don't need to restore + ;; ... stack status because callin convention is __z88dk_callee + +.include /cpct_drawSpriteMaskedColorizeM1.asm/ + +dms_restore_ix: + ld ix, #0000 ;; [4] Restore IX before returning + ret ;; [3] Return to caller \ No newline at end of file diff --git a/examples/medium/colorReplace/src/asm/sprites/colorReplace/M1/cpct_spriteColorizeM1.asm b/examples/medium/colorReplace/src/asm/sprites/colorReplace/M1/cpct_spriteColorizeM1.asm new file mode 100644 index 000000000..c29c6d050 --- /dev/null +++ b/examples/medium/colorReplace/src/asm/sprites/colorReplace/M1/cpct_spriteColorizeM1.asm @@ -0,0 +1,194 @@ +;;-----------------------------LICENSE NOTICE------------------------------------ +;; This file is part of CPCtelera: An Amstrad CPC Game Engine +;; Copyright (C) 2017 Arnaud Bouche (Arnaud6128) +;; Copyright (C) 2017 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) +;; +;; This program is free software: you can redistribute it and/or modify +;; it under the terms of the GNU Lesser General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU Lesser General Public License for more details. +;; +;; You should have received a copy of the GNU Lesser General Public License +;; along with this program. If not, see <http://www.gnu.org/licenses/>. +;;------------------------------------------------------------------------------- +.module cpct_sprites + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; +;; Function: cpct_spriteColorizeM1 +;; +;; Replace a color in a sprite and copy to another or the same sprite. +;; +;; C Definition: +;; void <cpct_spriteColorizeM1> (void* *sprite*, void* *spriteColor*, <u8> *width*, <u8> *height*, <u8> *oldColor*, <u8> *newColor*) __z88dk_callee; +;; +;; Input Parameters (6 bytes): +;; (2B HL') sprite - Source Sprite Pointer (array of pixel data) +;; (2B DE') spriteColor - Destination Sprite Pointer (can be also the Source Sprite) (array of pixel data) +;; (1B C' ) height - Sprite Height in bytes (>0) +;; (1B B' ) width - Sprite Width in *bytes* (Beware, *not* in pixels!) +;; (1B L ) oldColor - Color to replace +;; (1B H ) newColor - New color +;; +;; Assembly call (Input parameters on registers): +;; > call cpct_spriteColorizeM1_asm +;; +;; Parameter Restrictions: +;; * *sprite* must be an array containing sprite's pixels data in screen pixel format. +;; Sprite must be rectangular and all bytes in the array must be consecutive pixels, +;; starting from top-left corner and going left-to-right, top-to-bottom down to the +;; bottom-right corner. Total amount of bytes in pixel array should be *width* x *height*. +;; * *spriteColor* must be an array containing the new sprite's pixels data with the new color. +;; * *width* must be the width of the sprite *in bytes*. Always remember that the width must be +;; expressed in bytes and *not* in pixels. +;; The correspondence is mode 1 : 1 byte = 4 pixels +;; * *height* must be the height of the sprite in bytes, and must be greater than 0. +;; There is no practical upper limit to this value. Height of a sprite in +;; bytes and pixels is the same value, as bytes only group consecutive pixels in +;; the horizontal space. +;; * *oldColor* must be the index of color (0 to 3) to replace +;; * *newColor* must be the index of the new color (0 to 3) +;; +;; Known limitations: +;; * This function *will not work from ROM*, as it uses self-modifying code. +;; * This function requires the CPC firmware to be DISABLED. Otherwise, random crashes might happen due to side effects. +;; +;; Destroyed Register values: +;; AF, BC, DE, HL, BC', DE', HL', IX +;; +;; Required memory: +;; C-bindings - 73 bytes +;; ASM-bindings - 60 bytes +;; +;; Time Measures: +;; (start code) +;; Case | microSecs (us) | CPU Cycles +;; ---------------------------------------------------------------- +;; | 29 + (6 + 61W)H | 116 + (24 + 244W)H +;; ---------------------------------------------------------------- +;; W=2,H=16 | 2077 | 8308 +;; W=4,H=32 | 8029 | 32116 +;; ---------------------------------------------------------------- +;; Asm saving | -16 | -64 +;; ---------------------------------------------------------------- +;; (end code) +;; W = *width* in bytes, H = *height* in bytes +;; +;; Credits: +;; Original routine optimized by @Docent and discussed in CPCWiki : +;; http://www.cpcwiki.eu/forum/programming/cpctelera-colorize-sprite/ +;; +;; Thanks to all of them for their help and support. +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +.globl dc_mode1_ct + +;; Macro to convert color to pixel Mode1 : Axxx Axxx +.macro convertPixel ;; From cpct_px2byteM1 + ld bc, #dc_mode1_ct ;; [3] BC points to conversion table (dc_mode1_ct) + + ;; Compute HL += A + add c ;; [1] | C += A + ld c, a ;; [1] | + sub a ;; [1] A = 0 (preserving Carry Flag) + adc b ;; [1] | L += Carry + ld b, a ;; [1] | + + ;; A = *(BC + A) + ld a, (bc) ;; [2] A = Value stored at the table pointed by BC +.endm + + ;; Convert newColor to pixel format (E) + ld a, h ;; [1] A = H new color index + convertPixel ;; [10] | Convert into A + ld e, a ;; [1] | E = A new color : Axxx Axxx + + ;; Convert oldColor to pixel format (D) + ld a, l ;; [1] A = L old color index + convertPixel ;; [10] | Convert into A + ld d, a ;; [1] | D = A old color : Axxx Axxx + + ld c, #0x88 ;; [2] C = First Mask to get pixel A : Axxx Axxx + + exx ;; [1] Switch to Alternate registers + + ld__ixl_c ;; [1] IXL = C (Width) + ld c, b ;; [1] C = B (Height) + +convertLoop: + ld__b_ixl ;; [2] B = IXL (Sprite Width) + +lineLoop: + ld a, (hl) ;; [2] A = (HL) current Byte of sprite + exx ;; [1] Switch to Default registers + + ld l, a ;; [1] L = A current Byte of sprite : ABCD ABCD + and c ;; [2] A |= C (C = 0x88) : Axxx Axxx + + cp d ;; [1] Test if pixel (A) is the old colour to be replaced (D) + jr nz, readPixelA ;; [2/3] If not equal go to next pixel + ld a, e ;; [1] else A = new colour to set (E) + +readPixelA: + ld h, a ;; [1] H = A (current colorized sprite) : Axxx Axxx + + sla l ;; [2] L (current byte of sprite) << 1 : ABCD ABCD -> BCDx BCDx + ld a, l ;; [1] A = L : BCDx BCDx + and c ;; [2] A |= Mask (0x88) : Bxxx Bxxx + + cp d ;; [1] Test if pixel (A) is the old colour to be replaced (D) + jr nz, readPixelB ;; [2/3] If not equal go to next pixel + ld a, e ;; [1] else A = new colour to set (E) + +readPixelB: + rrca ;; [1] A = Axxx Axxx >> 1 : xBxx xBxx + or h ;; [1] A |= H (color byte) : Axxx Axxx + ld h, a ;; [1] H = A : ABxx ABxx + + sla l ;; [2] L ( BCDx BCDx) << 1 : CDxx CDxx + ld a, l ;; [1] A = L : CDxx CDxx + and c ;; [1] A |= C (C = 0x88) : Cxxx Cxxx + + cp d ;; [1] Test if pixel (A) is the old colour to be replaced (D) + jr nz, readPixelC ;; [2/3] If not equal go to next pixel + ld a, e ;; [1] else A = new colour to set (E) + +readPixelC: + rrca ;; [1] A = Axxx Axxx >> 1 : xBxx xBxx + rrca ;; [1] A = xxCx xxCx << 1 : xxCx xxCx + or h ;; [1] A |= H (ABxx ABxx) : ABCx ABCx + ld h, a ;; [1] H = A : ABCx ABCx + + sla l ;; [2] L (BCDx BCDx) << 1 : Dxxx Dxxx + ld a, l ;; [1] A = L : Dxxx Dxxx + and c ;; [1] A |= C (C = 0x88) : Dxxx Dxxx + + cp d ;; [1] Test if pixel (A) is the old colour to be replaced (D) + jr nz, readPixelD ;; [2/3] If not equal go to next pixel + ld a, e ;; [1] else A = new colour to set (E) + +readPixelD: + rrca ;; [1] A = Axxx Axxx >> 1 : xBxx xBxx + rrca ;; [1] A = xBxx xBxx >> 1 : xxCx xxCx + rrca ;; [1] A = xxCx xxxx >> 1 : xxxD xxxD + or h ;; [1] A |= H (ABCx ABCx) : ABCD ABCD + +setByte: + exx ;; [1] Switch to Alternate registers + + ld (de), a ;; [2] Update current sprite byte with pixels + inc hl ;; [2] Next byte sprite source + inc de ;; [2] Next byte sprite colorized + djnz lineLoop ;; [3] Decrement B (Width) if != 0 goto lineLoop + +nextLine: + dec c ;; [1] Decrement C (Height) + jr nz, convertLoop ;; [2/3] If != O goto convertLoop + +end: + ;; Return is included in bindings + diff --git a/examples/medium/colorReplace/src/asm/sprites/colorReplace/M1/cpct_spriteColorizeM1_asmbindings.s b/examples/medium/colorReplace/src/asm/sprites/colorReplace/M1/cpct_spriteColorizeM1_asmbindings.s new file mode 100644 index 000000000..4deb6e35b --- /dev/null +++ b/examples/medium/colorReplace/src/asm/sprites/colorReplace/M1/cpct_spriteColorizeM1_asmbindings.s @@ -0,0 +1,35 @@ +;;-----------------------------LICENSE NOTICE------------------------------------ +;; This file is part of CPCtelera: An Amstrad CPC Game Engine +;; Copyright (C) 2017 Arnaud Bouche (Arnaud6128) +;; Copyright (C) 2017 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) +;; +;; This program is free software: you can redistribute it and/or modify +;; it under the terms of the GNU Lesser General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU Lesser General Public License for more details. +;; +;; You should have received a copy of the GNU Lesser General Public License +;; along with this program. If not, see <http://www.gnu.org/licenses/>. +;;------------------------------------------------------------------------------- +.module cpct_sprites + +.include "../../../macros/cpct_undocumentedOpcodes.s" + +;; +;; ASM bindings for <cpct_spriteColorizeM1> +;; +cpct_spriteColorizeM1_asm:: ;; Assembly entry point + + ;; GET Parameters from the stack + ld (dms_restore_ix + 2), ix ;; [6] Save IX to restore it before returning + +.include /cpct_spriteColorizeM1.asm/ + +dms_restore_ix: + ld ix, #0000 ;; [4] Restore IX before returning + ret ;; [3] Return to caller \ No newline at end of file diff --git a/examples/medium/colorReplace/src/asm/sprites/colorReplace/M1/cpct_spriteColorizeM1_cbindings.s b/examples/medium/colorReplace/src/asm/sprites/colorReplace/M1/cpct_spriteColorizeM1_cbindings.s new file mode 100644 index 000000000..8bca05567 --- /dev/null +++ b/examples/medium/colorReplace/src/asm/sprites/colorReplace/M1/cpct_spriteColorizeM1_cbindings.s @@ -0,0 +1,48 @@ +;;-----------------------------LICENSE NOTICE------------------------------------ +;; This file is part of CPCtelera: An Amstrad CPC Game Engine +;; Copyright (C) 2017 Arnaud Bouche (Arnaud6128) +;; Copyright (C) 2017 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) +;; +;; This program is free software: you can redistribute it and/or modify +;; it under the terms of the GNU Lesser General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU Lesser General Public License for more details. +;; +;; You should have received a copy of the GNU Lesser General Public License +;; along with this program. If not, see <http://www.gnu.org/licenses/>. +;;------------------------------------------------------------------------------- +.module cpct_sprites + +.include "../../../macros/cpct_undocumentedOpcodes.s" + +;; +;; C bindings for <cpct_spriteColorizeM1> +;; +;; 33 us, 13 bytes +;; +_cpct_spriteColorizeM1:: + + ;; GET Parameters from the stack + ld (dms_restore_ix + 2), ix ;; [6] Save IX to restore it before returning + pop hl ;; [3] HL = Return Address + + exx + pop hl ;; [3] HL' = Source address (Sprite) + pop de ;; [3] DE' = Destination Sprite color + pop bc ;; [5] BC' = (B = Sprite Height, C = Width) + exx + + ex (sp), hl ;; [6] HL = (H = newColor, L = oldColor) + ;; ... and leave Return Address at (SP) as we don't need to restore + ;; ... stack status because callin convention is __z88dk_callee + +.include /cpct_spriteColorizeM1.asm/ + +dms_restore_ix: + ld ix, #0000 ;; [4] Restore IX before returning + ret ;; [3] Return to caller \ No newline at end of file diff --git a/examples/medium/colorReplace/src/asm/sprites/colorReplace/M1/cpct_spriteMaskedColorizeM1.asm b/examples/medium/colorReplace/src/asm/sprites/colorReplace/M1/cpct_spriteMaskedColorizeM1.asm new file mode 100644 index 000000000..82ccbb375 --- /dev/null +++ b/examples/medium/colorReplace/src/asm/sprites/colorReplace/M1/cpct_spriteMaskedColorizeM1.asm @@ -0,0 +1,205 @@ +;;-----------------------------LICENSE NOTICE------------------------------------ +;; This file is part of CPCtelera: An Amstrad CPC Game Engine +;; Copyright (C) 2017 Arnaud Bouche (Arnaud6128) +;; Copyright (C) 2017 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) +;; +;; This program is free software: you can redistribute it and/or modify +;; it under the terms of the GNU Lesser General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU Lesser General Public License for more details. +;; +;; You should have received a copy of the GNU Lesser General Public License +;; along with this program. If not, see <http://www.gnu.org/licenses/>. +;;------------------------------------------------------------------------------- +.module cpct_sprites +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; +;; Function: cpct_spriteMaskedColorizeM1 +;; +;; Replace a color in a Masked sprite and copy to another or the same sprite. +;; +;; C Definition: +;; void <cpct_spriteMaskedColorizeM1> (void* *sprite*, void* *spriteColor*, <u8> *width*, <u8> *height*, <u8> *oldColor*, <u8> *newColor*) __z88dk_callee; +;; +;; Input Parameters (6 bytes): +;; (2B HL') sprite - Source Sprite Pointer (array of pixel data) +;; (2B DE') spriteColor - Destination Sprite Pointer (can be also the Source Sprite) (array of pixel data) +;; (1B C') height - Sprite Height in bytes (>0) +;; (1B B') width - Sprite Width in *bytes* (Beware, *not* in pixels!) +;; (1B L) oldColor - Color to replace +;; (1B H) newColor - New color +;; +;; Assembly call (Input parameters on registers): +;; > call cpct_spriteMaskedColorizeM1_asm +;; +;; Parameter Restrictions: +;; * *sprite* must be an array containing sprite's pixels data in screen pixel format +;; along with mask data. Each mask byte will contain enabled bits as those that should +;; be picked from the background (transparent) and disabled bits for those that will +;; be printed from sprite colour data. Each mask data byte must precede its associated +;; colour data byte. +;; Sprite must be rectangular and all bytes in the array must be consecutive pixels, +;; starting from top-left corner and going left-to-right, top-to-bottom down to the +;; bottom-right corner. Total amount of bytes in pixel array should be +;; 2 x *width* x *height* (mask data doubles array size). +;; * *spriteColor* must be an array containing the new sprite's pixels data with the new color. +;; Total amount of bytes in pixel array should be 2 x *width* x *height* (mask data doubles array size). +;; * *width* must be the width of the sprite *in bytes*. Always remember that the width must be +;; expressed in bytes and *not* in pixels. +;; The correspondence is mode 1 : 1 byte = 4 pixels +;; * *height* must be the height of the sprite in bytes, and must be greater than 0. +;; There is no practical upper limit to this value. Height of a sprite in +;; bytes and pixels is the same value, as bytes only group consecutive pixels in +;; the horizontal space. +;; * *oldColor* must be the index of color (0 to 3) to replace +;; * *newColor* must be the index of the new color (0 to 3) +;; +;; Known limitations: +;; * This function *will not work from ROM*, as it uses self-modifying code. +;; * This function requires the CPC firmware to be DISABLED. Otherwise, random crashes might happen due to side effects. +;; +;; Destroyed Register values: +;; AF, BC, DE, HL, BC', DE', HL', IX +;; +;; Required memory: +;; C-bindings - 110 bytes +;; ASM-bindings - 97 bytes +;; +;; Time Measures: +;; (start code) +;; Case | microSecs (us) | CPU Cycles +;; ---------------------------------------------------------------- +;; | 29 + (6 + 71W)H | 116 + (24 + 284W)H +;; ---------------------------------------------------------------- +;; W=2,H=16 | 2397 | 9588 +;; W=4,H=32 | 9309 | 37236 +;; ---------------------------------------------------------------- +;; Asm saving | -16 | -64 +;; ---------------------------------------------------------------- +;; (end code) +;; W = *width* in bytes, H = *height* in bytes +;; +;; Credits: +;; Original routine optimized by @Docent and discussed in CPCWiki : +;; http://www.cpcwiki.eu/forum/programming/cpctelera-colorize-sprite/ +;; +;; Thanks to all of them for their help and support. +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +.globl dc_mode1_ct + +;; Macro to convert color to pixel Mode1 : Axxx Axxx +.macro convertPixel ;; From cpct_px2byteM1 + ld bc, #dc_mode1_ct ;; [3] HL points to conversion table (dc_mode1_ct) + + ;; Compute HL += A + add c ;; [1] | L += A + ld c, a ;; [1] | + sub a ;; [1] A = 0 (preserving Carry Flag) + adc b ;; [1] | H += Carry + ld b, a ;; [1] | + + ;; A = *(HL + A) + ld a, (bc) ;; [2] A = Value stored at the table pointed by HL +.endm + + ;; Convert newColor to pixel format (E) + ld a, h ;; [1] A = H new color index + convertPixel ;; [10] | Convert into A + ld e, a ;; [1] | E = A new color : Axxx Axxx + + ;; Convert oldColor to pixel format (D) + ld a, l ;; [1] A = L old color index + convertPixel ;; [10] | Convert into A + ld d, a ;; [1] | D = A old color : Axxx Axxx + + ld c, #0x88 ;; [2] C = First Mask to get pixel A : Axxx Axxx + + exx ;; [1] Switch to Alternate registers + + ld__ixl_c ;; [1] IXL = C (Width) + ld c, b ;; [1] C = B (Height) + +convertLoop: + ld__b_ixl ;; [2] B = IXL (Sprite Width) + +lineLoop: + ld a, (hl) ;; [2] A = (HL) current Byte of sprite Mask + ld (de), a ;; [2] (DE) = A Copy of sprite Mask + inc hl ;; [2] Next byte sprite Color source + inc de ;; [2] Next byte sprite Color destination + ld a, (hl) ;; [2] A = (HL) current Byte of sprite Color + + exx ;; [1] Switch to Default registers + + ld l, a ;; [1] L = A current Byte of sprite : ABCD ABCD + + and c ;; [2] A |= C (C = 0x88) : Axxx Axxx + + cp d ;; [1] Test if pixel (A) is the old colour to be replaced (D) + jr nz, readPixelA ;; [2/3] If not equal go to next pixel + ld a, e ;; [1] else A = new colour to set (E) + +readPixelA: + ld h, a ;; [1] H = A (current colorized sprite) : Axxx Axxx + + sla l ;; [2] L (current byte of sprite) << 1 : ABCD ABCD -> BCDx BCDx + ld a, l ;; [1] A = L : BCDx BCDx + and c ;; [2] A |= Mask (0x88) : Bxxx Bxxx + + cp d ;; [1] Test if pixel (A) is the old colour to be replaced (D) + jr nz, readPixelB ;; [2/3] If not equal go to next pixel + ld a, e ;; [1] else A = new colour to set (E) + +readPixelB: + rrca ;; [1] A = Axxx Axxx >> 1 : xBxx xBxx + or h ;; [1] A |= H (color byte) : Axxx Axxx + ld h, a ;; [1] H = A : ABxx ABxx + + sla l ;; [2] L ( BCDx BCDx) << 1 : CDxx CDxx + ld a, l ;; [1] A = L : CDxx CDxx + and c ;; [1] A |= C (C = 0x88) : Cxxx Cxxx + + cp d ;; [1] Test if pixel (A) is the old colour to be replaced (D) + jr nz, readPixelC ;; [2/3] If not equal go to next pixel + ld a, e ;; [1] else A = new colour to set (E) + +readPixelC: + rrca ;; [1] A = Axxx Axxx >> 1 : xBxx xBxx + rrca ;; [1] A = xxCx xxCx << 1 : xxCx xxCx + or h ;; [1] A |= H (ABxx ABxx) : ABCx ABCx + ld h, a ;; [1] H = A : ABCx ABCx + + sla l ;; [2] L (BCDx BCDx) << 1 : Dxxx Dxxx + ld a, l ;; [1] A = L : Dxxx Dxxx + and c ;; [1] A |= C (C = 0x88) : Dxxx Dxxx + + cp d ;; [1] Test if pixel (A) is the old colour to be replaced (D) + jr nz, readPixelD ;; [2/3] If not equal go to next pixel + ld a, e ;; [1] else A = new colour to set (E) + +readPixelD: + rrca ;; [1] A = Axxx Axxx >> 1 : xBxx xBxx + rrca ;; [1] A = xBxx xBxx >> 1 : xxCx xxCx + rrca ;; [1] A = xxCx xxxx >> 1 : xxxD xxxD + or h ;; [1] A |= H (ABCx ABCx) : ABCD ABCD + +setByte: + exx ;; [1] Switch to Alternate registers + + ld (de), a ;; [2] Update current sprite byte with pixels + inc hl ;; [2] Next byte sprite source + inc de ;; [2] Next byte sprite colorized + djnz lineLoop ;; [3] Decrement B (Width) if != 0 goto lineLoop + +nextLine: + dec c ;; [1] Decrement C (Height) + jr nz, convertLoop ;; [2/3] If != O goto convertLoop + +end: + ;; Return is included in bindings \ No newline at end of file diff --git a/examples/medium/colorReplace/src/asm/sprites/colorReplace/M1/cpct_spriteMaskedColorizeM1_asmbindings.s b/examples/medium/colorReplace/src/asm/sprites/colorReplace/M1/cpct_spriteMaskedColorizeM1_asmbindings.s new file mode 100644 index 000000000..cc7d49e23 --- /dev/null +++ b/examples/medium/colorReplace/src/asm/sprites/colorReplace/M1/cpct_spriteMaskedColorizeM1_asmbindings.s @@ -0,0 +1,36 @@ +;;-----------------------------LICENSE NOTICE------------------------------------ +;; This file is part of CPCtelera: An Amstrad CPC Game Engine +;; Copyright (C) 2017 Arnaud Bouche (Arnaud6128) +;; Copyright (C) 2017 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) +;; +;; This program is free software: you can redistribute it and/or modify +;; it under the terms of the GNU Lesser General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU Lesser General Public License for more details. +;; +;; You should have received a copy of the GNU Lesser General Public License +;; along with this program. If not, see <http://www.gnu.org/licenses/>. +;;------------------------------------------------------------------------------- +.module cpct_sprites + +.include "../../../macros/cpct_undocumentedOpcodes.s" + +;; +;; ASM bindings for <cpct_spriteMaskedColorizeM1> +;; +cpct_spriteMaskedColorizeM1_asm:: ;; Assembly entry point + + ;; GET Parameters from the stack + ld (dms_restore_ix + 2), ix ;; [6] Save IX to restore it before returning + pop hl ;; [3] HL = Return Address + +.include /cpct_spriteMaskedColorizeM1.asm/ + +dms_restore_ix: + ld ix, #0000 ;; [4] Restore IX before returning + ret ;; [3] Return to caller \ No newline at end of file diff --git a/examples/medium/colorReplace/src/asm/sprites/colorReplace/M1/cpct_spriteMaskedColorizeM1_cbindings.s b/examples/medium/colorReplace/src/asm/sprites/colorReplace/M1/cpct_spriteMaskedColorizeM1_cbindings.s new file mode 100644 index 000000000..3e4784f8a --- /dev/null +++ b/examples/medium/colorReplace/src/asm/sprites/colorReplace/M1/cpct_spriteMaskedColorizeM1_cbindings.s @@ -0,0 +1,48 @@ +;;-----------------------------LICENSE NOTICE------------------------------------ +;; This file is part of CPCtelera: An Amstrad CPC Game Engine +;; Copyright (C) 2017 Arnaud Bouche (Arnaud6128) +;; Copyright (C) 2017 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) +;; +;; This program is free software: you can redistribute it and/or modify +;; it under the terms of the GNU Lesser General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU Lesser General Public License for more details. +;; +;; You should have received a copy of the GNU Lesser General Public License +;; along with this program. If not, see <http://www.gnu.org/licenses/>. +;;------------------------------------------------------------------------------- +.module cpct_sprites + +.include "../../../macros/cpct_undocumentedOpcodes.s" + +;; +;; C bindings for <cpct_spriteMaskedColorizeM1> +;; +;; 33 us, 13 bytes +;; +_cpct_spriteMaskedColorizeM1:: + + ;; GET Parameters from the stack + ld (dms_restore_ix + 2), ix ;; [6] Save IX to restore it before returning + pop hl ;; [3] HL = Return Address + + exx + pop hl ;; [3] HL' = Source address (Sprite) + pop de ;; [3] DE' = Destination Sprite color + pop bc ;; [5] BC' = (B = Sprite Height, C = Width) + exx + + ex (sp), hl ;; [6] HL = (H = newColor, L = oldColor) + ;; ... and leave Return Address at (SP) as we don't need to restore + ;; ... stack status because callin convention is __z88dk_callee + +.include /cpct_spriteMaskedColorizeM1.asm/ + +dms_restore_ix: + ld ix, #0000 ;; [4] Restore IX before returning + ret ;; [3] Return to caller \ No newline at end of file diff --git a/examples/medium/colorReplace/src/declarations.h b/examples/medium/colorReplace/src/declarations.h new file mode 100644 index 000000000..0c25f2044 --- /dev/null +++ b/examples/medium/colorReplace/src/declarations.h @@ -0,0 +1,90 @@ +//-----------------------------LICENSE NOTICE------------------------------------ +// This file is part of CPCtelera: An Amstrad CPC Game Engine +// Copyright (C) 2017 Arnaud BOUCHE +// Copyright (C) 2017 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +//------------------------------------------------------------------------------ + +#ifndef _DECLARATIONS_H_ +#define _DECLARATIONS_H_ + +///////////////////////////////////////////////////////////////////////////////// +// INCLUDES +#include <cpctelera.h> + +// Sprites +#include "sprites/baloon.h" +#include "sprites/roof.h" +#include "sprites/cloud.h" +#include "sprites/square.h" +#include "sprites/star_trans.h" +#include "sprites/circle_trans.h" + +// Other modules +#include "manageVideoMem.h" +#include "drawing.h" + +///////////////////////////////////////////////////////////////////////////////// +// USEFUL MACROS AND CONSTANTS +// + +// Memory location definition +enum +{ + VIDEO_MEM, + BUFFER_MEM, + NB_BUFFERS +}; + +// Boolean definition +#define BOOL u8 +#define TRUE 1 +#define FALSE 0 + +// Double buffer location +#define SCREEN_BUFF 0x8000 +#define VMEM_SIZE 0x4000 + +// Mask table location +#define MASK_TABLE_LOC (SCREEN_BUFF - 0x100) // 0x100 = Size of Mask Table + +// New stack location +#define NEW_STACK_LOC (MASK_TABLE_LOC - 0x100) // 0x100 = Size of Stack + +// Screen size +#define SCREEN_CY 200 +#define SCREEN_CX 80 + +#define VIEW_TOP 0 +#define VIEW_DOWN SCREEN_CY - 20 + +#define POS_CLOUD_X 0 +#define POS_CLOUD_Y 20 + +#define NB_BALOONS 8 +#define BALOON_TRAIL 8 + +#define BALOON_ACTIVE 1 +#define BALOON_INACTIVE 0 + +#define NB_STARS 10 +#define NB_COLORS_STAR 7 + +///////////////////////////////////////////////////////////////////////////////// +// Mask Table Definition for Mode 0 +// +cpctm_declareMaskTable(gMaskTable); + +#endif \ No newline at end of file diff --git a/examples/medium/colorReplace/src/drawing.c b/examples/medium/colorReplace/src/drawing.c new file mode 100644 index 000000000..7a6bfc72b --- /dev/null +++ b/examples/medium/colorReplace/src/drawing.c @@ -0,0 +1,371 @@ + +//-----------------------------LICENSE NOTICE------------------------------------ +// This file is part of CPCtelera: An Amstrad CPC Game Engine +// Copyright (C) 2017 Bouche Arnaud +// Copyright (C) 2017 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +//------------------------------------------------------------------------------ + +#include "declarations.h" + +///////////////////////////////////////////////////////////////////////////////// +// GLOBAL VARIABLES +u8 gSpriteColorized[G_BALOON_W*G_BALOON_H]; // Array for sprite to color +u8 gBackGroundColor; // Background color +u8 gBaloonColor; // Current color baloon +u8 gPosCloud; // Position of cloude + +///////////////////////////////////////////////////////////////////////////////// +// STRUCTURES DEFINITION +typedef struct TBaloon // Baloon structure +{ + i16 posY; // Absolute Baloon PosY (can be outside screen) + u8 posX; // Absolute Baloon PosX + + u8 drawPosY; // In screen Baloon PosY + u8 drawCY; // In screen Baloon Height + + u8 speed; // Baloon speed + u8 color; // Baloon color drawn + + u8 status; // Baloon status ACTIVE / INACTIVE +} SBaloon; + +typedef struct TBaloons // All baloons structure +{ + u8 nb; // Nb baloons in screen + SBaloon baloons[NB_BALOONS]; // Array of baloon +} SBaloons; + +SBaloons gBaloons; // Baloons to draw + +typedef struct TStar // Lighting star structure +{ + u8 posX; // Screen PosX + u8 posY; // Screen PosY + + u8 color; // Star color drawn +} SStar; + +typedef struct TStars // All stars structure +{ + SStar stars[NB_STARS]; // Array of stars +} SStars; + +SStars gStars; // Stars to draw + +/////////////////////////////////////////////////////// +/// GET RANDOM FROM 0 TO MAX-1 +/// +u8 GetRand(u8 max) +{ + return cpct_rand()%max; +} + +/////////////////////////////////////////////////////// +/// CHANGE TWO COLORS OF BALOON SPRITE +/// +void ColorSprite(u8 color) +{ + // Replace the two colors 1 and 2 of sprite baloon + cpct_spriteColorizeM0(g_baloon, gSpriteColorized, G_BALOON_W, G_BALOON_H, 1, color); // Colors are consecutives + cpct_spriteColorizeM0(gSpriteColorized, gSpriteColorized, G_BALOON_W, G_BALOON_H, 2, color + 1); +} + +/////////////////////////////////////////////////////// +/// CLEAR BALOON BACKGROUND +/// +void ClearBaloon(SBaloon* baloon) +{ + // If baloon in visible part of view + if (baloon->drawPosY < VIEW_DOWN) + { + u8* pvmem; + + // Compute size to be filled with background color + u8 clearCY = baloon->drawCY + BALOON_TRAIL; + + // Compute position to clear + u8 posDownClearY = baloon->drawPosY + clearCY; + if (posDownClearY > VIEW_DOWN) + clearCY = VIEW_DOWN - baloon->drawPosY; + + // Draw the box with background color to clear + pvmem = GetBackBufferPtr(baloon->posX, baloon->drawPosY); + cpct_drawSolidBox(pvmem, gBackGroundColor, G_BALOON_W, clearCY); + } +} + +/////////////////////////////////////////////////////// +/// DELETE BALOON +/// +void DeleteBaloons(SBaloon* baloons, SBaloon* baloonToDel, u8* nb) +{ + // Get last baloon in array + // Decrement number of remaining baloons in array + const SBaloon* lastBaloon = &baloons[--*nb]; + + // Replace baloon to be deleted with last baloon (if they are not the same) + if (baloonToDel != lastBaloon) + cpct_memcpy(baloonToDel, lastBaloon, sizeof(SBaloon)); +} + +/////////////////////////////////////////////////////// +/// UPDATE BALOONS +/// +void UpdateBaloons() +{ + SBaloon* itBaloon = gBaloons.baloons; + u8 i; + + // Test if we can add a new baloon + if (gBaloons.nb < NB_BALOONS) + { + // Add new baloon at end of array + // Increment number of baloons in array + SBaloon* newBaloon = &gBaloons.baloons[gBaloons.nb++]; + + // Get random positions X and Y + newBaloon->posX = GetRand(SCREEN_CX - G_BALOON_W); + newBaloon->posY = SCREEN_CY - GetRand(40); + + // Get random speed + newBaloon->speed = GetRand(3) + 2; + + // Get circular next color 2 by 2 until 12 + gBaloonColor = (gBaloonColor + 2) % 12; + newBaloon->color = gBaloonColor + 1; + + // Set baloon ACTIVE + newBaloon->status = BALOON_ACTIVE; + } + + // Update all baloons + for (i = 0; i < gBaloons.nb; i++) + { + // If baloon active move and draw it + if (itBaloon->status == BALOON_ACTIVE) + { + // Test if whole baloon outside view + if (itBaloon->posY + G_BALOON_H < VIEW_TOP) + { + // Set baloon inactive + itBaloon->status = BALOON_INACTIVE; + // Clear baloon background + ClearBaloon(itBaloon); + } + else + { + // Move baloon to up according its speed + i16 posY = itBaloon->posY - itBaloon->speed; + itBaloon->posY = posY; + + // Baloon outside view by top + if (posY < VIEW_TOP) + { + itBaloon->drawPosY = 0; + itBaloon->drawCY = G_BALOON_H + posY; + } + else + // Baloon outside view by down + if (posY + G_BALOON_H > VIEW_DOWN) + { + itBaloon->drawPosY = posY; + itBaloon->drawCY = VIEW_DOWN - posY; + } + // Baloon all in view + else + { + itBaloon->drawPosY = posY; + itBaloon->drawCY = G_BALOON_H; + } + } + } + // If inactive delete baloon + else + { + // Clear baloon background + ClearBaloon(itBaloon); + + // Delete baloon from list + DeleteBaloons(gBaloons.baloons, itBaloon, &gBaloons.nb); + } + + // Get next baloon pointer + itBaloon++; + } +} + +/////////////////////////////////////////////////////// +/// DRAW BALOON +/// +void DrawBaloon(SBaloon* baloon, const u8* spriteBaloon) +{ + i16 posY = baloon->posY; + + // If baloon in view + if (posY + G_BALOON_H > VIEW_TOP && posY < VIEW_DOWN) + { + // Get VMem pointer of current baloon position + u8* pvmem = GetBackBufferPtr(baloon->posX, baloon->drawPosY); + const u8* sprite = (u8*)spriteBaloon; + + // Baloon partialy outside view by top + if (posY < VIEW_TOP) + { + // Compute Y position + u8 y = -posY; + + // Compute sprite offset + sprite = (u8*)spriteBaloon + G_BALOON_W * y; + } + + cpct_drawSpriteMaskedAlignedTable(sprite, pvmem, G_BALOON_W, baloon->drawCY, gMaskTable); + } +} + +/////////////////////////////////////////////////////// +/// DRAW STARS +/// +void DrawStars() +{ + // Static stars color + const static u8 sColorStar[NB_COLORS_STAR] = { 2, 4, 7, 8, 10, 11, 12 }; + static u8 color = 0; + + u8 i; + for (i = 0; i < NB_STARS; i++) + { + // Get video pointer of each star to be drawn + u8* pvmem = GetBackBufferPtr(gStars.stars[i].posX, gStars.stars[i].posY); + u8 color = gStars.stars[i].color++; + + // Use different drawing color methods + if (i < NB_STARS/3) + { + // Color and draw masked sprite in video memory + cpct_drawSpriteMaskedColorizeM0(g_star_trans, pvmem, G_STAR_TRANS_W, G_STAR_TRANS_H, 15, sColorStar[color]); + } + else if (i > NB_STARS/3 && i < 2*NB_STARS/3) + { + // Color and draw masked aligned sprite in video memory + cpct_drawSpriteMaskedAlignedColorizeM0(g_square, pvmem, G_SQUARE_W, G_SQUARE_H, 15, sColorStar[color], gMaskTable); + } + else + { + // Color and copy masked sprite in temporary array + u8 circleColor[G_CIRCLE_TRANS_W * G_CIRCLE_TRANS_H * 2]; + cpct_spriteMaskedColorizeM0(g_circle_trans, circleColor, G_CIRCLE_TRANS_W, G_CIRCLE_TRANS_H, 15, sColorStar[color]); + + // Draw masked Sprite from temporary array + cpct_drawSpriteMasked(circleColor, pvmem, G_CIRCLE_TRANS_W, G_CIRCLE_TRANS_H); + } + + // If all colors palette used restart from 0 + if (color == NB_COLORS_STAR - 1) + gStars.stars[i].color = 0; + } +} + +/////////////////////////////////////////////////////// +/// DRAW CLOUD +/// +void DrawCloud() +{ + // Draw cloud at fixed place + u8* pvmem = GetBackBufferPtr(0, POS_CLOUD_Y); + cpct_drawSprite(g_cloud, pvmem, G_CLOUD_W, G_CLOUD_H); +} + +/////////////////////////////////////////////////////// +/// DRAW SCENE WITH ALL BALOONS +/// +void DrawSceneBaloons() +{ + u8 i; + + // Clear background for all baloons + SBaloon* itBaloon = gBaloons.baloons; // Get first baloon pointer + for (i = 0; i < gBaloons.nb; i++) + { + ClearBaloon(itBaloon); + itBaloon++; + } + + // Draw sprite cloud + DrawCloud(); + + // Draw all baloons + itBaloon = gBaloons.baloons; // Get first baloon pointer + for (i = 0; i < gBaloons.nb; i++) + { + const u8* sprite = g_baloon; // Default baloon sprite (blue) + + // Test if sprite have colors to change + if (itBaloon->color > 1) // Color 0 (white) is transparent color + { + ColorSprite(itBaloon->color); // Change colors of ballon + sprite = gSpriteColorized; // Sprite to draw is colorized baloon + } + + DrawBaloon(itBaloon, sprite); // Draw baloon sprite + itBaloon++; // Get next baloon + } +} + +/////////////////////////////////////////////////////// +/// DRAW BACKGROUND BLUE SKY AND ROOF +/// +void DrawBackground() +{ + u8* pvmem; + + // Fill video buffer with background color + cpct_memset((u8*)SCREEN_BUFF, gBackGroundColor, VMEM_SIZE); + + // Draw left part of Roof + pvmem = GetBackBufferPtr(0, SCREEN_CY-G_ROOF_H); + cpct_drawSprite(g_roof, pvmem, G_ROOF_W, G_ROOF_H); + + // Draw right part of Roof + pvmem += G_ROOF_W; + cpct_drawSprite(g_roof, pvmem, G_ROOF_W, G_ROOF_H); + + // Copy Same background on both buffers + cpct_memcpy(CPCT_VMEM_START, (u8*)SCREEN_BUFF, VMEM_SIZE); +} + +///////////////////////////////////////////////////////////////////////////////// +/// INITIALIZE DRAWING +/// +/// Initializes global variables and general status for drawing functions +/// +void InitializeDrawing() +{ + u8 dx = SCREEN_CX / NB_STARS; // Compute space between stars + + u8 i; + for (i = 0; i < NB_STARS; i++) + { + gStars.stars[i].posX = dx * i + 5; // Constant space beetween stars + gStars.stars[i].posY = GetRand(10) + 175; // Random Y position from 175 to 184 + gStars.stars[i].color = GetRand(NB_COLORS_STAR); // Random color from 0 to NB_COLORS_STAR-1 + } + + gBackGroundColor = cpct_px2byteM0(14, 14); // Get byte color of background for M0 + gBaloons.nb = 0; // No baloon to draw at start + + DrawBackground(); // Set background on both buffers +} diff --git a/examples/medium/colorReplace/src/drawing.h b/examples/medium/colorReplace/src/drawing.h new file mode 100644 index 000000000..ad41ea5e4 --- /dev/null +++ b/examples/medium/colorReplace/src/drawing.h @@ -0,0 +1,31 @@ +//-----------------------------LICENSE NOTICE------------------------------------ +// This file is part of CPCtelera: An Amstrad CPC Game Engine +// Copyright (C) 2017 Bouche Arnaud +// Copyright (C) 2017 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +//------------------------------------------------------------------------------ + +#ifndef _DRAWING_H_ +#define _DRAWING_H_ + +//////////////////////////////////////////////////////////////////////////////////////////// +// PUBLIC FUNCTION DECLARATIONS +// +void InitializeDrawing(); +void UpdateBaloons(); +void DrawSceneBaloons(); +void DrawStars(); + +#endif \ No newline at end of file diff --git a/examples/medium/colorReplace/src/main.c b/examples/medium/colorReplace/src/main.c new file mode 100644 index 000000000..b405a67f7 --- /dev/null +++ b/examples/medium/colorReplace/src/main.c @@ -0,0 +1,69 @@ +//-----------------------------LICENSE NOTICE------------------------------------ +// This file is part of CPCtelera: An Amstrad CPC Game Engine +// Copyright (C) 2017 Arnaud BOUCHE +// Copyright (C) 2017 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +//------------------------------------------------------------------------------ + +#include "declarations.h" + +///////////////////////////////////////////////////////////////////////////////// +// Mask Table Definition for Mode 0 +// +cpctm_createTransparentMaskTable(gMaskTable, MASK_TABLE_LOC, M0, 0); + +/////////////////////////////////////////////////////// +/// INITIALIZATION +/// +// Initializes the CPC and all systems before starting the main loop +// +void Initialization() +{ + // We need to disable firmware in order to set the palette and + // to be able to use a second screen between 0x8000 and 0xBFFF + cpct_disableFirmware(); + cpct_setVideoMode(0); // Set mode 0 + cpct_setPalette(g_palette, 16); // Set the palette + cpct_setBorder(0x57); // Set the border color with Hardware color (Sky Blue) + + InitializeVideoMemoryBuffers(); // Initialize video buffers + InitializeDrawing(); // Initialize drawing elements +} + +/////////////////////////////////////////////////////// +/// MAIN PROGRAM +/// +void main(void) +{ + // Change stack location before any call. We will be using + // memory from 0x8000 to 0xBFFF as secondary buffer, so + // the stack must not be there or it will get overwritten + cpct_setStackLocation((u8*)NEW_STACK_LOC); + + // Initialize everything + Initialization(); + + // Main Loop + while (TRUE) + { + UpdateBaloons(); + DrawSceneBaloons(); + DrawStars(); + + // Flip buffers to display the present back buffer + // and stop displaying the current video memory + FlipBuffers(); + } +} diff --git a/examples/medium/colorReplace/src/manageVideoMem.c b/examples/medium/colorReplace/src/manageVideoMem.c new file mode 100644 index 000000000..1314592cd --- /dev/null +++ b/examples/medium/colorReplace/src/manageVideoMem.c @@ -0,0 +1,88 @@ +//-----------------------------LICENSE NOTICE------------------------------------ +// This file is part of CPCtelera: An Amstrad CPC Game Engine +// Copyright (C) 2017 Bouche Arnaud +// Copyright (C) 2017 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +//------------------------------------------------------------------------------ + +#include "declarations.h" + +///////////////////////////////////////////////////////////////////////////////// +// GLOBAL VARIABLES +// +u8 gVMem; // Current video mem + +///////////////////////////////////////////////////////////////////////////////// +// INITITALIZE VIDEO MEMORY BUFFERS +// Initializes tracking of video memory buffers +// +void InitializeVideoMemoryBuffers() { + gVMem = VIDEO_MEM; +} + +///////////////////////////////////////////////////////////////////////////////// +// FLIPBUFFERS +// Interchanges present screen video memory for the present buffer memory. +// This change is made instantly, so all the contents of screen buffer are shown +// at once at the screen. Present screen memory now becomes the new screen +// buffer and viceversa, hence the name "FlipBuffer". +// In order to prevent intermediate flickering, this function waits until +// VSYNC signal is up before flipping both buffers +// +void FlipBuffers() { + cpct_waitVSYNC(); // Wait until VSYNC is up + + // Depending on present video memory, flip from + // Video to Buffer or from Buffer to Video + if (gVMem == BUFFER_MEM) { + cpct_setVideoMemoryPage(cpct_pageC0); + gVMem = VIDEO_MEM; + } else { + cpct_setVideoMemoryPage(cpct_page80); + gVMem = BUFFER_MEM; + } +} + +///////////////////////////////////////////////////////////////////////////////// +// GET SCREEN PTR +// Gets a pointer to a (x,y) location in the current video memory +// +u8* GetScreenPtr(u8 xPos, u8 yPos) { + u8* screenStart; + + // Screen video memory start depends on which hardware + // buffer is currently being used as video memory + if (gVMem == VIDEO_MEM) screenStart = (u8*)CPCT_VMEM_START; + else screenStart = (u8*)SCREEN_BUFF; + + // Calculate and return screen pointer + return cpct_getScreenPtr(screenStart, xPos, yPos); +} + +///////////////////////////////////////////////////////////////////////////////// +// GET BACK BUFFER PTR +// Gets a pointer to a (x,y) location in the present hardware back buffer +// +u8* GetBackBufferPtr(u8 xPos, u8 yPos) { + u8* backBufferStart; + + // Hardware back buffer memory start depends on which hardware + // buffer is currently being used as video memory + if (gVMem == VIDEO_MEM) backBufferStart = (u8*)SCREEN_BUFF; + else backBufferStart = (u8*)CPCT_VMEM_START; + + // Calculate and return screen pointer + return cpct_getScreenPtr(backBufferStart, xPos, yPos); +} \ No newline at end of file diff --git a/examples/medium/colorReplace/src/manageVideoMem.h b/examples/medium/colorReplace/src/manageVideoMem.h new file mode 100644 index 000000000..7f3ee4ed4 --- /dev/null +++ b/examples/medium/colorReplace/src/manageVideoMem.h @@ -0,0 +1,47 @@ +//-----------------------------LICENSE NOTICE------------------------------------ +// This file is part of CPCtelera: An Amstrad CPC Game Engine +// Copyright (C) 2017 Bouche Arnaud +// Copyright (C) 2017 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +//------------------------------------------------------------------------------ + +//////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////// +// MANAGE VIDEO MEMORY +// +// This module groups functions and variables that control video memory. These functions +// take care of which memory is being used as screen video memory and which as hardware +// back buffer. They also switch both buffers on demand. +// This module also controls the function tu perform drawing from a sprite back buffer +// to video memory. When all drawings are finished, and after waiting to VSYNC signal, +// the Sprite Back Buffer is then drawn as one big sprite to screen. This final unique +// operation is fast enough to avoid being caught by raster, then avoiding flickering. +//////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////// + +#ifndef _MANAGEVIDEOMEM_H_ +#define _MANAGEVIDEOMEM_H_ + +#include <cpctelera.h> + +//////////////////////////////////////////////////////////////////////////////////////////// +// PUBLIC FUNCTION DECLARATIONS +// +void InitializeVideoMemoryBuffers (); +u8* GetScreenPtr (u8 xPos, u8 yPos); +u8* GetBackBufferPtr (u8 xPos, u8 yPos); +void FlipBuffers (); + +#endif \ No newline at end of file diff --git a/examples/medium/colorReplace/src/sprites/baloon.c b/examples/medium/colorReplace/src/sprites/baloon.c new file mode 100644 index 000000000..79910f7bc --- /dev/null +++ b/examples/medium/colorReplace/src/sprites/baloon.c @@ -0,0 +1,43 @@ +#include "baloon.h" +// Data created with Img2CPC - (c) Retroworks - 2007-2015 +// Palette uses hardware values. +const u8 g_palette[16] = { 0x40, 0x44, 0x55, 0x5c, 0x4c, 0x58, 0x5d, 0x4d, 0x4f, 0x56, 0x52, 0x4e, 0x4a, 0x54, 0x57, 0x4b }; + +// Tile g_baloon: 20x34 pixels, 10x34 bytes. +const u8 g_baloon[10 * 34] = { + 0x00, 0x00, 0x00, 0x51, 0xf3, 0xf3, 0xa2, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x51, 0xa6, 0x0c, 0x0c, 0x59, 0xa2, 0x00, 0x00, + 0x00, 0x00, 0xa6, 0xae, 0x0c, 0x0c, 0x0c, 0x59, 0x00, 0x00, + 0x00, 0x51, 0xae, 0x0c, 0xae, 0x0c, 0x0c, 0x0c, 0xa2, 0x00, + 0x00, 0xa6, 0x0c, 0xae, 0x0c, 0x0c, 0x0c, 0x0c, 0x59, 0x00, + 0x51, 0x5d, 0x5d, 0xff, 0x5d, 0x0c, 0x0c, 0x0c, 0x0c, 0xa2, + 0x51, 0x0c, 0x0c, 0xae, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0xa2, + 0x51, 0x0c, 0xae, 0x0c, 0xae, 0x0c, 0x0c, 0x0c, 0x0c, 0xa2, + 0xa6, 0x0c, 0x0c, 0xae, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x59, + 0xa6, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x59, + 0xa6, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x59, + 0xa6, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x59, + 0xa6, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x59, + 0xa6, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x59, + 0xa6, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x59, + 0xa6, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x59, + 0xa6, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x59, + 0xa6, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x59, + 0x51, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0xa2, + 0x51, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0xa2, + 0x51, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0xa2, + 0x00, 0xa6, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x59, 0x00, + 0x00, 0xa6, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x59, 0x00, + 0x00, 0x51, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0xa2, 0x00, + 0x00, 0x00, 0xa6, 0x0c, 0x0c, 0x0c, 0x0c, 0x59, 0x00, 0x00, + 0x00, 0x00, 0xe2, 0x0c, 0x0c, 0x0c, 0x0c, 0xd1, 0x00, 0x00, + 0x00, 0x00, 0x51, 0xc0, 0x0c, 0x0c, 0xc0, 0xa2, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xe2, 0x84, 0x48, 0xd1, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x51, 0xc0, 0xc0, 0xa2, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xe2, 0xd1, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xe7, 0xdb, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x51, 0xc0, 0xc0, 0xa2, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xe2, 0xe2, 0xd1, 0xd1, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x51, 0x51, 0xa2, 0xa2, 0x00, 0x00, 0x00 +}; + diff --git a/examples/medium/colorReplace/src/sprites/baloon.h b/examples/medium/colorReplace/src/sprites/baloon.h new file mode 100644 index 000000000..e9fc3e64f --- /dev/null +++ b/examples/medium/colorReplace/src/sprites/baloon.h @@ -0,0 +1,12 @@ +// Data created with Img2CPC - (c) Retroworks - 2007-2015 +#ifndef _IMG_BALOON_H_ +#define _IMG_BALOON_H_ + +#include <types.h> +extern const u8 g_palette[16]; + +#define G_BALOON_W 10 +#define G_BALOON_H 34 +extern const u8 g_baloon[10 * 34]; + +#endif diff --git a/examples/medium/colorReplace/src/sprites/circle_trans.c b/examples/medium/colorReplace/src/sprites/circle_trans.c new file mode 100644 index 000000000..30b2a8876 --- /dev/null +++ b/examples/medium/colorReplace/src/sprites/circle_trans.c @@ -0,0 +1,12 @@ +#include "circle_trans.h" +// Data created with Img2CPC - (c) Retroworks - 2007-2015 +// Tile g_circle_trans: 4x6 pixels, 2x6 bytes. +const u8 g_circle_trans[2 * 2 * 6] = { + 0xaa, 0x55, 0xff, 0x00, + 0x00, 0xff, 0x55, 0xaa, + 0x00, 0xff, 0x55, 0xaa, + 0x00, 0xff, 0x55, 0xaa, + 0x00, 0xff, 0x55, 0xaa, + 0xaa, 0x55, 0xff, 0x00 +}; + diff --git a/examples/medium/colorReplace/src/sprites/circle_trans.h b/examples/medium/colorReplace/src/sprites/circle_trans.h new file mode 100644 index 000000000..a3dbf1367 --- /dev/null +++ b/examples/medium/colorReplace/src/sprites/circle_trans.h @@ -0,0 +1,10 @@ +// Data created with Img2CPC - (c) Retroworks - 2007-2015 +#ifndef _IMG_CIRCLE_TRANS_H_ +#define _IMG_CIRCLE_TRANS_H_ + +#include <types.h> +#define G_CIRCLE_TRANS_W 2 +#define G_CIRCLE_TRANS_H 6 +extern const u8 g_circle_trans[2 * 2 * 6]; + +#endif diff --git a/examples/medium/colorReplace/src/sprites/cloud.c b/examples/medium/colorReplace/src/sprites/cloud.c new file mode 100644 index 000000000..6400be15d --- /dev/null +++ b/examples/medium/colorReplace/src/sprites/cloud.c @@ -0,0 +1,60 @@ +#include "cloud.h" +// Data created with Img2CPC - (c) Retroworks - 2007-2015 +// Tile g_cloud: 62x54 pixels, 31x54 bytes. +const u8 g_cloud[31 * 54] = { + 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x7f, 0xbf, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, + 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0xff, 0xff, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, + 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0xff, 0xff, 0xff, 0xbf, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, + 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, + 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, + 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, + 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, + 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, + 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, + 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, + 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, + 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, + 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, + 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, + 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, + 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, + 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, + 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, + 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, + 0x3f, 0x3f, 0x3f, 0x3f, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x7f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, + 0x3f, 0x3f, 0x3f, 0x3f, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, + 0x3f, 0x3f, 0x3f, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, + 0x3f, 0x3f, 0x3f, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, + 0x3f, 0x3f, 0x3f, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0x3f, 0x3f, 0x3f, 0x3f, + 0x3f, 0x3f, 0x3f, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x3f, + 0x3f, 0x3f, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0x3f, + 0x3f, 0x3f, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0x3f, + 0x3f, 0x3f, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, + 0x3f, 0x3f, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, + 0x3f, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, + 0x3f, 0x3f, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, + 0x3f, 0x3f, 0xff, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0xbf, + 0x3f, 0x3f, 0x7f, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, + 0x3f, 0x3f, 0xbf, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0xff, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, + 0x3f, 0x3f, 0x7f, 0x7f, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, + 0x3f, 0x3f, 0x3f, 0xbf, 0xbf, 0xbf, 0xff, 0xff, 0xff, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0xbf, + 0x3f, 0x3f, 0x3f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0xff, 0xff, 0xff, 0x7f, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x7f, 0xff, 0xff, 0x7f, + 0x3f, 0x3f, 0x3f, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xff, 0xbf, 0xff, 0xff, 0xff, 0xbf, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0xbf, 0xff, 0xff, 0xbf, 0xbf, + 0x3f, 0x3f, 0x3f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x7f, 0xff, 0x7f, 0x7f, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, + 0x3f, 0x3f, 0x3f, 0x3f, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xff, 0xff, 0xbf, 0xbf, 0xff, 0xff, 0xbf, 0xbf, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0xff, 0xbf, 0xbf, 0xbf, 0xbf, + 0x3f, 0x3f, 0x3f, 0x3f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0xff, 0xff, 0x7f, 0x7f, 0xff, 0xff, 0x7f, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xff, 0x7f, 0x7f, 0x3f, 0x3f, + 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xff, 0xff, 0xbf, 0xbf, 0xbf, 0xff, 0xbf, 0xff, 0xbf, 0xff, 0xbf, 0xbf, 0xff, 0xbf, 0xbf, 0xbf, 0x3f, + 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0xff, 0xff, 0x7f, 0x7f, 0xff, 0xff, 0xff, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0xff, 0x7f, 0x7f, 0x3f, 0x3f, + 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0xbf, 0x3f, 0x3f, 0x3f, 0x3f, 0xbf, 0xbf, 0xbf, 0xbf, 0xff, 0xbf, 0xbf, 0xff, 0xbf, 0xbf, 0xff, 0xbf, 0xbf, 0xbf, 0xff, 0xbf, 0xbf, 0xbf, 0xbf, 0x3f, + 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x3f, 0x3f, + 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0xbf, 0xbf, 0xbf, 0x3f, 0x3f, 0xbf, 0xbf, 0xff, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0x3f, 0x3f, 0x3f, + 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x7f, 0x3f, 0x3f, 0x3f, 0x7f, 0x7f, 0xff, 0xff, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x3f, 0x3f, 0x3f, 0x3f, + 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0xbf, 0xff, 0xbf, 0xff, 0xff, 0xbf, 0xbf, 0xbf, 0xbf, 0x3f, 0x3f, 0x3f, 0x3f, + 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x7f, 0x7f, 0xff, 0xff, 0x7f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, + 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, + 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, + 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0xbf, 0xbf, 0xbf, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, + 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x7f, 0x7f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, + 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0xbf, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f +}; + diff --git a/examples/medium/colorReplace/src/sprites/cloud.h b/examples/medium/colorReplace/src/sprites/cloud.h new file mode 100644 index 000000000..d6fc74738 --- /dev/null +++ b/examples/medium/colorReplace/src/sprites/cloud.h @@ -0,0 +1,10 @@ +// Data created with Img2CPC - (c) Retroworks - 2007-2015 +#ifndef _IMG_CLOUD_H_ +#define _IMG_CLOUD_H_ + +#include <types.h> +#define G_CLOUD_W 31 +#define G_CLOUD_H 54 +extern const u8 g_cloud[31 * 54]; + +#endif diff --git a/examples/medium/colorReplace/src/sprites/roof.c b/examples/medium/colorReplace/src/sprites/roof.c new file mode 100644 index 000000000..aa3a87955 --- /dev/null +++ b/examples/medium/colorReplace/src/sprites/roof.c @@ -0,0 +1,26 @@ +#include "roof.h" +// Data created with Img2CPC - (c) Retroworks - 2007-2015 +// Tile g_roof: 80x20 pixels, 40x20 bytes. +const u8 g_roof[40 * 20] = { + 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xd9, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xd9, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xd9, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xd9, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xd9, + 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x71, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x71, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x71, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x71, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x71, + 0x30, 0x64, 0x64, 0x64, 0x64, 0xcf, 0xcc, 0xd9, 0x30, 0x64, 0x64, 0x64, 0x64, 0xcf, 0xcc, 0xd9, 0x30, 0x64, 0x64, 0x64, 0x64, 0xcf, 0xcc, 0xd9, 0x30, 0x64, 0x64, 0x64, 0x64, 0xcf, 0xcc, 0xd9, 0x30, 0x64, 0x64, 0x64, 0x64, 0xcf, 0xcc, 0xd9, + 0xce, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xd9, 0xce, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xd9, 0xce, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xd9, 0xce, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xd9, 0xce, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xd9, + 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xd9, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xd9, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xd9, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xd9, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xd9, + 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, + 0xcc, 0xcc, 0xe6, 0xe6, 0xe6, 0x98, 0xe6, 0xcc, 0xe6, 0xcc, 0xe6, 0xcc, 0xe6, 0xcc, 0xe6, 0xcc, 0xcc, 0xcc, 0xe6, 0xe6, 0xe6, 0xcc, 0xe6, 0xcc, 0xe6, 0xcc, 0xe6, 0xcc, 0xe6, 0xcc, 0xe6, 0xcc, 0xcc, 0xcc, 0xe6, 0xe6, 0xe6, 0xcc, 0xe6, 0x98, + 0xb2, 0x30, 0xf3, 0xb2, 0xb2, 0x30, 0xb2, 0x71, 0xb2, 0x30, 0xf3, 0x30, 0xb2, 0x30, 0xb2, 0x71, 0xb2, 0x30, 0xf3, 0xb2, 0xb2, 0x30, 0xb2, 0x71, 0xb2, 0x30, 0xf3, 0x30, 0xb2, 0x30, 0xb2, 0x71, 0xb2, 0x30, 0xf3, 0xb2, 0xb2, 0x30, 0xb2, 0x71, + 0xb2, 0x30, 0xf3, 0x71, 0xb2, 0x30, 0xf3, 0xf3, 0xb2, 0x30, 0xf3, 0x71, 0xb2, 0x30, 0xf3, 0xf3, 0xb2, 0x30, 0xf3, 0x71, 0xb2, 0x30, 0xf3, 0xf3, 0xb2, 0x30, 0xf3, 0x71, 0xb2, 0x30, 0xf3, 0xf3, 0xb2, 0x30, 0xf3, 0xd9, 0xb2, 0x30, 0xf3, 0xf3, + 0xf3, 0xf3, 0xb2, 0x30, 0xf3, 0xf3, 0xe6, 0xcc, 0xf3, 0xf3, 0xe6, 0xcc, 0xf3, 0xf3, 0xe6, 0xcc, 0xf3, 0xf3, 0xb2, 0x30, 0xf3, 0xf3, 0xe6, 0xcc, 0xf3, 0xf3, 0xe6, 0xcc, 0xf3, 0xf3, 0xe6, 0xcc, 0xf3, 0xf3, 0xe6, 0x64, 0xf3, 0xf3, 0xe6, 0xcc, + 0xe6, 0xcc, 0xb2, 0x30, 0xe6, 0xcc, 0xb2, 0x30, 0xe6, 0xcc, 0xb2, 0x30, 0xe6, 0xcc, 0xb2, 0x30, 0xe6, 0xcc, 0xb2, 0x30, 0xe6, 0xcc, 0xb2, 0x30, 0xe6, 0xcc, 0xb2, 0x30, 0xe6, 0xcc, 0xb2, 0x30, 0xe6, 0xcc, 0xb2, 0x30, 0xe6, 0xcc, 0xb2, 0x30, + 0x65, 0x30, 0xb2, 0x64, 0xb2, 0x64, 0x30, 0x30, 0xb2, 0x30, 0xb2, 0x30, 0xe6, 0x30, 0x30, 0x30, 0xb2, 0x30, 0xe6, 0x30, 0xb2, 0x30, 0x98, 0x98, 0xb2, 0x30, 0xb2, 0x30, 0xb2, 0x30, 0x64, 0x30, 0xb2, 0x30, 0xb2, 0x30, 0xb2, 0x30, 0xb2, 0x64, + 0x65, 0x30, 0xb2, 0x98, 0xb2, 0x30, 0x30, 0x64, 0xb2, 0x30, 0xb2, 0x30, 0xb2, 0x30, 0x65, 0x30, 0xb2, 0x30, 0xb2, 0x64, 0xb2, 0x30, 0xcc, 0x30, 0xb2, 0x30, 0xb2, 0x98, 0xb2, 0x30, 0xcd, 0x30, 0xb2, 0x30, 0xe6, 0x64, 0xb2, 0x30, 0xe6, 0x30, + 0x65, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x64, 0xe7, 0x30, 0x30, 0x30, 0x64, 0x30, 0x65, 0x30, 0xe7, 0x30, 0x98, 0x30, 0x98, 0x30, 0x30, 0x30, 0xe7, 0x30, 0xcc, 0x30, 0x98, 0x30, 0x65, 0x30, 0xe7, 0x30, 0x98, 0x98, 0x30, 0x30, 0xb2, 0x98, + 0x65, 0xcf, 0x30, 0xcf, 0xe7, 0x30, 0x65, 0x30, 0xe7, 0xcf, 0x30, 0xcf, 0xe7, 0x30, 0x65, 0x9a, 0xe7, 0xcf, 0x30, 0xcf, 0xe7, 0x30, 0x65, 0x30, 0xe7, 0xcf, 0x30, 0xcf, 0xe7, 0x30, 0x65, 0x9a, 0xe7, 0xcf, 0x30, 0xcf, 0xe7, 0x64, 0x65, 0x30, + 0xe7, 0xcf, 0xe7, 0x9a, 0xe7, 0x9a, 0xb2, 0xdb, 0xe7, 0xcf, 0xe7, 0x9a, 0xe7, 0x9a, 0xb2, 0xdb, 0xe7, 0xcf, 0xe7, 0x9a, 0xe7, 0x9a, 0xb2, 0xdb, 0xe7, 0xcf, 0xe7, 0x9a, 0xe7, 0x9a, 0xb2, 0xdb, 0xe7, 0xcf, 0xe7, 0x9a, 0xe7, 0x9a, 0xb2, 0xdb, + 0xf3, 0x9a, 0xf3, 0xf3, 0xf3, 0x9a, 0xf3, 0xf3, 0xf3, 0x9a, 0xf3, 0xf3, 0xf3, 0x9a, 0xf3, 0xf3, 0xf3, 0x9a, 0xf3, 0xf3, 0xf3, 0x9a, 0xf3, 0xf3, 0xf3, 0x9a, 0xf3, 0xf3, 0xf3, 0x9a, 0xf3, 0xf3, 0xf3, 0x9a, 0xf3, 0xf3, 0xf3, 0x9a, 0xf3, 0xf3, + 0xf3, 0xf3, 0xb2, 0x30, 0xf3, 0xf3, 0xe6, 0xcc, 0xf3, 0xf3, 0xe6, 0xcc, 0xd9, 0xf3, 0xe6, 0xcc, 0xf3, 0xf3, 0xe6, 0xcc, 0xf3, 0xf3, 0xe6, 0xcc, 0xf3, 0xf3, 0xe6, 0xcc, 0xf3, 0xf3, 0xe6, 0xcc, 0xf3, 0xf3, 0xe6, 0xcc, 0xf3, 0xf3, 0xe6, 0xcc, + 0xe7, 0x30, 0xb2, 0x30, 0xb2, 0xcc, 0xb2, 0x30, 0xb2, 0x30, 0xb2, 0x30, 0xe6, 0xcc, 0xb2, 0x30, 0xe6, 0xcc, 0xb2, 0x30, 0xe6, 0xcc, 0xb2, 0x30, 0xe6, 0xcc, 0xb2, 0x30, 0xe6, 0xcc, 0xb2, 0x30, 0xe6, 0x98, 0xb2, 0x30, 0xe6, 0xcc, 0xb2, 0x30, + 0x65, 0x30, 0xe7, 0x30, 0xb2, 0x30, 0xb2, 0x30, 0x30, 0x30, 0xe7, 0x30, 0xb2, 0x30, 0xb2, 0x30, 0x30, 0x30, 0xe7, 0x30, 0xb2, 0x30, 0xb2, 0x30, 0x30, 0x30, 0xe7, 0x30, 0xb2, 0x30, 0xb2, 0x30, 0x30, 0x30, 0xe7, 0x30, 0xb2, 0x30, 0xb2, 0x30 +}; + diff --git a/examples/medium/colorReplace/src/sprites/roof.h b/examples/medium/colorReplace/src/sprites/roof.h new file mode 100644 index 000000000..f6d1e5a09 --- /dev/null +++ b/examples/medium/colorReplace/src/sprites/roof.h @@ -0,0 +1,10 @@ +// Data created with Img2CPC - (c) Retroworks - 2007-2015 +#ifndef _IMG_ROOF_H_ +#define _IMG_ROOF_H_ + +#include <types.h> +#define G_ROOF_W 40 +#define G_ROOF_H 20 +extern const u8 g_roof[40 * 20]; + +#endif diff --git a/examples/medium/colorReplace/src/sprites/square.c b/examples/medium/colorReplace/src/sprites/square.c new file mode 100644 index 000000000..acdfaea36 --- /dev/null +++ b/examples/medium/colorReplace/src/sprites/square.c @@ -0,0 +1,12 @@ +#include "square.h" +// Data created with Img2CPC - (c) Retroworks - 2007-2015 +// Tile g_square: 4x6 pixels, 2x6 bytes. +const u8 g_square[2 * 6] = { + 0xff, 0xaa, + 0xff, 0xaa, + 0xff, 0xaa, + 0xff, 0xaa, + 0xff, 0xaa, + 0xff, 0xaa +}; + diff --git a/examples/medium/colorReplace/src/sprites/square.h b/examples/medium/colorReplace/src/sprites/square.h new file mode 100644 index 000000000..693116632 --- /dev/null +++ b/examples/medium/colorReplace/src/sprites/square.h @@ -0,0 +1,10 @@ +// Data created with Img2CPC - (c) Retroworks - 2007-2015 +#ifndef _IMG_SQUARE_H_ +#define _IMG_SQUARE_H_ + +#include <types.h> +#define G_SQUARE_W 2 +#define G_SQUARE_H 6 +extern const u8 g_square[2 * 6]; + +#endif diff --git a/examples/medium/colorReplace/src/sprites/star_trans.c b/examples/medium/colorReplace/src/sprites/star_trans.c new file mode 100644 index 000000000..b11648f2f --- /dev/null +++ b/examples/medium/colorReplace/src/sprites/star_trans.c @@ -0,0 +1,12 @@ +#include "star_trans.h" +// Data created with Img2CPC - (c) Retroworks - 2007-2015 +// Tile g_star_trans: 4x6 pixels, 2x6 bytes. +const u8 g_star_trans[2 * 2 * 6] = { + 0xaa, 0x55, 0xff, 0x00, + 0xaa, 0x55, 0xff, 0x00, + 0x00, 0xff, 0x55, 0xaa, + 0x00, 0xff, 0x55, 0xaa, + 0xaa, 0x55, 0xff, 0x00, + 0xaa, 0x55, 0xff, 0x00 +}; + diff --git a/examples/medium/colorReplace/src/sprites/star_trans.h b/examples/medium/colorReplace/src/sprites/star_trans.h new file mode 100644 index 000000000..afdd9f47f --- /dev/null +++ b/examples/medium/colorReplace/src/sprites/star_trans.h @@ -0,0 +1,10 @@ +// Data created with Img2CPC - (c) Retroworks - 2007-2015 +#ifndef _IMG_STAR_TRANS_H_ +#define _IMG_STAR_TRANS_H_ + +#include <types.h> +#define G_STAR_TRANS_W 2 +#define G_STAR_TRANS_H 6 +extern const u8 g_star_trans[2 * 2 * 6]; + +#endif From 0e9364ac5dc30640ecd76ffd53ffae34893a7839 Mon Sep 17 00:00:00 2001 From: Arnaud <arnaud_bouche@hotmail.com> Date: Sat, 20 Jan 2018 12:07:25 +0100 Subject: [PATCH 05/31] Compilation error correction under cpctelera 1.4.2 --- .../colorReplace/M0/cpct_drawSpriteColorizeM0_asmbindings.s | 2 +- .../colorReplace/M0/cpct_drawSpriteColorizeM0_cbindings.s | 2 +- .../M0/cpct_drawSpriteMaskedAlignedColorizeM0_asmbindings.s | 2 +- .../M0/cpct_drawSpriteMaskedAlignedColorizeM0_cbindings.s | 2 +- .../M0/cpct_drawSpriteMaskedColorizeM0_asmbindings.s | 2 +- .../colorReplace/M0/cpct_drawSpriteMaskedColorizeM0_cbindings.s | 2 +- .../sprites/colorReplace/M0/cpct_spriteColorizeM0_asmbindings.s | 2 +- .../sprites/colorReplace/M0/cpct_spriteColorizeM0_cbindings.s | 2 +- .../colorReplace/M0/cpct_spriteMaskedColorizeM0_asmbindings.s | 2 +- .../colorReplace/M0/cpct_spriteMaskedColorizeM0_cbindings.s | 2 +- .../colorReplace/M1/cpct_drawSpriteColorizeM1_asmbindings.s | 2 +- .../colorReplace/M1/cpct_drawSpriteColorizeM1_cbindings.s | 2 +- .../M1/cpct_drawSpriteMaskedAlignedColorizeM1_asmbindings.s | 2 +- .../M1/cpct_drawSpriteMaskedAlignedColorizeM1_cbindings.s | 2 +- .../M1/cpct_drawSpriteMaskedColorizeM1_asmbindings.s | 2 +- .../colorReplace/M1/cpct_drawSpriteMaskedColorizeM1_cbindings.s | 2 +- .../sprites/colorReplace/M1/cpct_spriteColorizeM1_asmbindings.s | 2 +- .../sprites/colorReplace/M1/cpct_spriteColorizeM1_cbindings.s | 2 +- .../colorReplace/M1/cpct_spriteMaskedColorizeM1_asmbindings.s | 2 +- .../colorReplace/M1/cpct_spriteMaskedColorizeM1_cbindings.s | 2 +- 20 files changed, 20 insertions(+), 20 deletions(-) diff --git a/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteColorizeM0_asmbindings.s b/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteColorizeM0_asmbindings.s index d5930a9aa..7dd12e5e0 100644 --- a/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteColorizeM0_asmbindings.s +++ b/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteColorizeM0_asmbindings.s @@ -18,7 +18,7 @@ ;;------------------------------------------------------------------------------- .module cpct_sprites -.include "../../../macros/cpct_undocumentedOpcodes.s" +.include "../../../macros/cpct_undocumentedOpcodes.h.s" ;; ;; ASM bindings for <cpct_drawSpriteColorizeM0> diff --git a/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteColorizeM0_cbindings.s b/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteColorizeM0_cbindings.s index ac5d57084..063414615 100644 --- a/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteColorizeM0_cbindings.s +++ b/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteColorizeM0_cbindings.s @@ -18,7 +18,7 @@ ;;------------------------------------------------------------------------------- .module cpct_sprites -.include "../../../macros/cpct_undocumentedOpcodes.s" +.include "../../../macros/cpct_undocumentedOpcodes.h.s" ;; ;; C bindings for <cpct_drawSpriteColorizeM0> diff --git a/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteMaskedAlignedColorizeM0_asmbindings.s b/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteMaskedAlignedColorizeM0_asmbindings.s index 7828b8736..e5ea9de3f 100644 --- a/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteMaskedAlignedColorizeM0_asmbindings.s +++ b/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteMaskedAlignedColorizeM0_asmbindings.s @@ -18,7 +18,7 @@ ;;------------------------------------------------------------------------------- .module cpct_sprites -.include "../../../macros/cpct_undocumentedOpcodes.s" +.include "../../../macros/cpct_undocumentedOpcodes.h.s" ;; ;; ASM bindings for <cpct_drawSpriteMaskedAlignedColorizeM0> diff --git a/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteMaskedAlignedColorizeM0_cbindings.s b/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteMaskedAlignedColorizeM0_cbindings.s index 001ae99c3..6578e5ea5 100644 --- a/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteMaskedAlignedColorizeM0_cbindings.s +++ b/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteMaskedAlignedColorizeM0_cbindings.s @@ -18,7 +18,7 @@ ;;------------------------------------------------------------------------------- .module cpct_sprites -.include "../../../macros/cpct_undocumentedOpcodes.s" +.include "../../../macros/cpct_undocumentedOpcodes.h.s" ;; ;; C bindings for <cpct_drawSpriteMaskedAlignedColorizeM0> diff --git a/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteMaskedColorizeM0_asmbindings.s b/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteMaskedColorizeM0_asmbindings.s index 1a40a3186..4959e2abc 100644 --- a/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteMaskedColorizeM0_asmbindings.s +++ b/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteMaskedColorizeM0_asmbindings.s @@ -18,7 +18,7 @@ ;;------------------------------------------------------------------------------- .module cpct_sprites -.include "../../../macros/cpct_undocumentedOpcodes.s" +.include "../../../macros/cpct_undocumentedOpcodes.h.s" ;; ;; ASM bindings for <cpct_drawSpriteMaskedColorizeM0> diff --git a/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteMaskedColorizeM0_cbindings.s b/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteMaskedColorizeM0_cbindings.s index c39a879a4..212a5acc5 100644 --- a/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteMaskedColorizeM0_cbindings.s +++ b/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteMaskedColorizeM0_cbindings.s @@ -18,7 +18,7 @@ ;;------------------------------------------------------------------------------- .module cpct_sprites -.include "../../../macros/cpct_undocumentedOpcodes.s" +.include "../../../macros/cpct_undocumentedOpcodes.h.s" ;; ;; C bindings for <cpct_drawSpriteMaskedColorizeM0> diff --git a/cpctelera/src/sprites/colorReplace/M0/cpct_spriteColorizeM0_asmbindings.s b/cpctelera/src/sprites/colorReplace/M0/cpct_spriteColorizeM0_asmbindings.s index 9ac97a5e6..01f6d77b7 100644 --- a/cpctelera/src/sprites/colorReplace/M0/cpct_spriteColorizeM0_asmbindings.s +++ b/cpctelera/src/sprites/colorReplace/M0/cpct_spriteColorizeM0_asmbindings.s @@ -18,7 +18,7 @@ ;;------------------------------------------------------------------------------- .module cpct_sprites -.include "../../../macros/cpct_undocumentedOpcodes.s" +.include "../../../macros/cpct_undocumentedOpcodes.h.s" ;; ;; ASM bindings for <cpct_spriteColorizeM0> diff --git a/cpctelera/src/sprites/colorReplace/M0/cpct_spriteColorizeM0_cbindings.s b/cpctelera/src/sprites/colorReplace/M0/cpct_spriteColorizeM0_cbindings.s index f31436707..63dbf05a5 100644 --- a/cpctelera/src/sprites/colorReplace/M0/cpct_spriteColorizeM0_cbindings.s +++ b/cpctelera/src/sprites/colorReplace/M0/cpct_spriteColorizeM0_cbindings.s @@ -18,7 +18,7 @@ ;;------------------------------------------------------------------------------- .module cpct_sprites -.include "../../../macros/cpct_undocumentedOpcodes.s" +.include "../../../macros/cpct_undocumentedOpcodes.h.s" ;; ;; C bindings for <cpct_spriteColorizeM0> diff --git a/cpctelera/src/sprites/colorReplace/M0/cpct_spriteMaskedColorizeM0_asmbindings.s b/cpctelera/src/sprites/colorReplace/M0/cpct_spriteMaskedColorizeM0_asmbindings.s index 30440d708..9abbc1467 100644 --- a/cpctelera/src/sprites/colorReplace/M0/cpct_spriteMaskedColorizeM0_asmbindings.s +++ b/cpctelera/src/sprites/colorReplace/M0/cpct_spriteMaskedColorizeM0_asmbindings.s @@ -18,7 +18,7 @@ ;;------------------------------------------------------------------------------- .module cpct_sprites -.include "../../../macros/cpct_undocumentedOpcodes.s" +.include "../../../macros/cpct_undocumentedOpcodes.h.s" ;; ;; ASM bindings for <cpct_spriteMaskedColorizeM0> diff --git a/cpctelera/src/sprites/colorReplace/M0/cpct_spriteMaskedColorizeM0_cbindings.s b/cpctelera/src/sprites/colorReplace/M0/cpct_spriteMaskedColorizeM0_cbindings.s index a2bba9de5..9c9363f91 100644 --- a/cpctelera/src/sprites/colorReplace/M0/cpct_spriteMaskedColorizeM0_cbindings.s +++ b/cpctelera/src/sprites/colorReplace/M0/cpct_spriteMaskedColorizeM0_cbindings.s @@ -18,7 +18,7 @@ ;;------------------------------------------------------------------------------- .module cpct_sprites -.include "../../../macros/cpct_undocumentedOpcodes.s" +.include "../../../macros/cpct_undocumentedOpcodes.h.s" ;; ;; C bindings for <cpct_spriteMaskedColorizeM0> diff --git a/cpctelera/src/sprites/colorReplace/M1/cpct_drawSpriteColorizeM1_asmbindings.s b/cpctelera/src/sprites/colorReplace/M1/cpct_drawSpriteColorizeM1_asmbindings.s index 44ca0f2b0..e0ed27aff 100644 --- a/cpctelera/src/sprites/colorReplace/M1/cpct_drawSpriteColorizeM1_asmbindings.s +++ b/cpctelera/src/sprites/colorReplace/M1/cpct_drawSpriteColorizeM1_asmbindings.s @@ -18,7 +18,7 @@ ;;------------------------------------------------------------------------------- .module cpct_sprites -.include "../../../macros/cpct_undocumentedOpcodes.s" +.include "../../../macros/cpct_undocumentedOpcodes.h.s" ;; ;; ASM bindings for <cpct_drawSpriteColorizeM1> diff --git a/cpctelera/src/sprites/colorReplace/M1/cpct_drawSpriteColorizeM1_cbindings.s b/cpctelera/src/sprites/colorReplace/M1/cpct_drawSpriteColorizeM1_cbindings.s index 22798d0f3..21322d77c 100644 --- a/cpctelera/src/sprites/colorReplace/M1/cpct_drawSpriteColorizeM1_cbindings.s +++ b/cpctelera/src/sprites/colorReplace/M1/cpct_drawSpriteColorizeM1_cbindings.s @@ -18,7 +18,7 @@ ;;------------------------------------------------------------------------------- .module cpct_sprites -.include "../../../macros/cpct_undocumentedOpcodes.s" +.include "../../../macros/cpct_undocumentedOpcodes.h.s" ;; ;; C bindings for <cpct_drawSpriteColorizeM1> diff --git a/cpctelera/src/sprites/colorReplace/M1/cpct_drawSpriteMaskedAlignedColorizeM1_asmbindings.s b/cpctelera/src/sprites/colorReplace/M1/cpct_drawSpriteMaskedAlignedColorizeM1_asmbindings.s index db02086d7..853ba0bbe 100644 --- a/cpctelera/src/sprites/colorReplace/M1/cpct_drawSpriteMaskedAlignedColorizeM1_asmbindings.s +++ b/cpctelera/src/sprites/colorReplace/M1/cpct_drawSpriteMaskedAlignedColorizeM1_asmbindings.s @@ -18,7 +18,7 @@ ;;------------------------------------------------------------------------------- .module cpct_sprites -.include "../../../macros/cpct_undocumentedOpcodes.s" +.include "../../../macros/cpct_undocumentedOpcodes.h.s" ;; ;; ASM bindings for <cpct_drawSpriteMaskedAlignedColorizeM1> diff --git a/cpctelera/src/sprites/colorReplace/M1/cpct_drawSpriteMaskedAlignedColorizeM1_cbindings.s b/cpctelera/src/sprites/colorReplace/M1/cpct_drawSpriteMaskedAlignedColorizeM1_cbindings.s index f0b0a2130..9085b4a80 100644 --- a/cpctelera/src/sprites/colorReplace/M1/cpct_drawSpriteMaskedAlignedColorizeM1_cbindings.s +++ b/cpctelera/src/sprites/colorReplace/M1/cpct_drawSpriteMaskedAlignedColorizeM1_cbindings.s @@ -18,7 +18,7 @@ ;;------------------------------------------------------------------------------- .module cpct_sprites -.include "../../../macros/cpct_undocumentedOpcodes.s" +.include "../../../macros/cpct_undocumentedOpcodes.h.s" ;; ;; C bindings for <cpct_drawSpriteMaskedAlignedColorizeM1> diff --git a/cpctelera/src/sprites/colorReplace/M1/cpct_drawSpriteMaskedColorizeM1_asmbindings.s b/cpctelera/src/sprites/colorReplace/M1/cpct_drawSpriteMaskedColorizeM1_asmbindings.s index b2ed10933..b8b2ce518 100644 --- a/cpctelera/src/sprites/colorReplace/M1/cpct_drawSpriteMaskedColorizeM1_asmbindings.s +++ b/cpctelera/src/sprites/colorReplace/M1/cpct_drawSpriteMaskedColorizeM1_asmbindings.s @@ -18,7 +18,7 @@ ;;------------------------------------------------------------------------------- .module cpct_sprites -.include "../../../macros/cpct_undocumentedOpcodes.s" +.include "../../../macros/cpct_undocumentedOpcodes.h.s" ;; ;; ASM bindings for <cpct_drawSpriteMaskedColorizeM1> diff --git a/cpctelera/src/sprites/colorReplace/M1/cpct_drawSpriteMaskedColorizeM1_cbindings.s b/cpctelera/src/sprites/colorReplace/M1/cpct_drawSpriteMaskedColorizeM1_cbindings.s index aa21c471c..2c68ccd2b 100644 --- a/cpctelera/src/sprites/colorReplace/M1/cpct_drawSpriteMaskedColorizeM1_cbindings.s +++ b/cpctelera/src/sprites/colorReplace/M1/cpct_drawSpriteMaskedColorizeM1_cbindings.s @@ -18,7 +18,7 @@ ;;------------------------------------------------------------------------------- .module cpct_sprites -.include "../../../macros/cpct_undocumentedOpcodes.s" +.include "../../../macros/cpct_undocumentedOpcodes.h.s" ;; ;; C bindings for <cpct_drawSpriteMaskedColorizeM1> diff --git a/cpctelera/src/sprites/colorReplace/M1/cpct_spriteColorizeM1_asmbindings.s b/cpctelera/src/sprites/colorReplace/M1/cpct_spriteColorizeM1_asmbindings.s index 4deb6e35b..1de96a3fa 100644 --- a/cpctelera/src/sprites/colorReplace/M1/cpct_spriteColorizeM1_asmbindings.s +++ b/cpctelera/src/sprites/colorReplace/M1/cpct_spriteColorizeM1_asmbindings.s @@ -18,7 +18,7 @@ ;;------------------------------------------------------------------------------- .module cpct_sprites -.include "../../../macros/cpct_undocumentedOpcodes.s" +.include "../../../macros/cpct_undocumentedOpcodes.h.s" ;; ;; ASM bindings for <cpct_spriteColorizeM1> diff --git a/cpctelera/src/sprites/colorReplace/M1/cpct_spriteColorizeM1_cbindings.s b/cpctelera/src/sprites/colorReplace/M1/cpct_spriteColorizeM1_cbindings.s index 8bca05567..c7cb8916f 100644 --- a/cpctelera/src/sprites/colorReplace/M1/cpct_spriteColorizeM1_cbindings.s +++ b/cpctelera/src/sprites/colorReplace/M1/cpct_spriteColorizeM1_cbindings.s @@ -18,7 +18,7 @@ ;;------------------------------------------------------------------------------- .module cpct_sprites -.include "../../../macros/cpct_undocumentedOpcodes.s" +.include "../../../macros/cpct_undocumentedOpcodes.h.s" ;; ;; C bindings for <cpct_spriteColorizeM1> diff --git a/cpctelera/src/sprites/colorReplace/M1/cpct_spriteMaskedColorizeM1_asmbindings.s b/cpctelera/src/sprites/colorReplace/M1/cpct_spriteMaskedColorizeM1_asmbindings.s index cc7d49e23..6119b9763 100644 --- a/cpctelera/src/sprites/colorReplace/M1/cpct_spriteMaskedColorizeM1_asmbindings.s +++ b/cpctelera/src/sprites/colorReplace/M1/cpct_spriteMaskedColorizeM1_asmbindings.s @@ -18,7 +18,7 @@ ;;------------------------------------------------------------------------------- .module cpct_sprites -.include "../../../macros/cpct_undocumentedOpcodes.s" +.include "../../../macros/cpct_undocumentedOpcodes.h.s" ;; ;; ASM bindings for <cpct_spriteMaskedColorizeM1> diff --git a/cpctelera/src/sprites/colorReplace/M1/cpct_spriteMaskedColorizeM1_cbindings.s b/cpctelera/src/sprites/colorReplace/M1/cpct_spriteMaskedColorizeM1_cbindings.s index 3e4784f8a..8592b429f 100644 --- a/cpctelera/src/sprites/colorReplace/M1/cpct_spriteMaskedColorizeM1_cbindings.s +++ b/cpctelera/src/sprites/colorReplace/M1/cpct_spriteMaskedColorizeM1_cbindings.s @@ -18,7 +18,7 @@ ;;------------------------------------------------------------------------------- .module cpct_sprites -.include "../../../macros/cpct_undocumentedOpcodes.s" +.include "../../../macros/cpct_undocumentedOpcodes.h.s" ;; ;; C bindings for <cpct_spriteMaskedColorizeM1> From 81ec623f8bef83d8477920c5be17c5e783fff2b6 Mon Sep 17 00:00:00 2001 From: Arnaud <arnaud_bouche@hotmail.com> Date: Sat, 20 Jan 2018 12:39:41 +0100 Subject: [PATCH 06/31] Add cpct_getScreenToSprite to header --- cpctelera/src/video/videomode.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/cpctelera/src/video/videomode.h b/cpctelera/src/video/videomode.h index 761a3c9a6..dc53c6057 100644 --- a/cpctelera/src/video/videomode.h +++ b/cpctelera/src/video/videomode.h @@ -47,4 +47,7 @@ extern u8* cpct_getScreenPtr (void* screen_start, u8 x, u8 y) __z88dk_callee; // Change Screen Resolutions setting CRTC register values extern void cpct_setCRTCReg (u8 regnum, u8 newval) __z88dk_callee; +// Capture Video Memory area to buffer +extern void cpct_getScreenToSprite(u8* memory, u8* sprite, u8 width, u8 height) __z88dk_callee; + #endif From bb5e4160f904927e23e2da1d1d5320c538429fc7 Mon Sep 17 00:00:00 2001 From: Arnaud <arnaud_bouche@hotmail.com> Date: Sat, 20 Jan 2018 12:40:35 +0100 Subject: [PATCH 07/31] Add cpct_getScreenToSprite function to video --- .../src/video/cpct_getScreenToSprite.asm | 131 ++++++++++++++++++ .../cpct_getScreenToSprite_asmbindings.s | 29 ++++ .../video/cpct_getScreenToSprite_cbindings.s | 39 ++++++ 3 files changed, 199 insertions(+) create mode 100644 cpctelera/src/video/cpct_getScreenToSprite.asm create mode 100644 cpctelera/src/video/cpct_getScreenToSprite_asmbindings.s create mode 100644 cpctelera/src/video/cpct_getScreenToSprite_cbindings.s diff --git a/cpctelera/src/video/cpct_getScreenToSprite.asm b/cpctelera/src/video/cpct_getScreenToSprite.asm new file mode 100644 index 000000000..2cc41fd48 --- /dev/null +++ b/cpctelera/src/video/cpct_getScreenToSprite.asm @@ -0,0 +1,131 @@ +;;-----------------------------LICENSE NOTICE------------------------------------ +;; This file is part of CPCtelera: An Amstrad CPC Game Engine +;; Copyright (C) 2014-2015 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) +;; +;; This program is free software: you can redistribute it and/or modify +;; it under the terms of the GNU Lesser General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU Lesser General Public License for more details. +;; +;; You should have received a copy of the GNU Lesser General Public License +;; along with this program. If not, see <http://www.gnu.org/licenses/>. +;;------------------------------------------------------------------------------- +.module cpct_sprites + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; +;; Function: cpct_drawSpriteMasked +;; +;; Copies and convert part of the screen to sprite +;; +;; C Definition: +;; void <cpct_getScreenToSprite> (void* *memory*, void* *sprite*, <u8> *width*, <u8> *height*) __z88dk_callee; +;; +;; Input Parameters (6 bytes): +;; (2B DE) memory - Source Screen Address (Video memory location) +;; (2B HL) sprite - Destination Sprite Address (Sprite data array) +;; (1B C ) width - Sprite Width in *bytes* (>0) (Beware, *not* in pixels!) +;; (1B B ) height - Sprite Height in bytes (>0) +;; +;; Assembly call (Input parameters on registers): +;; > call cpct_getScreenToSprite_asm +;; +;; Parameter Restrictions: +;; * *memory* could be any place in memory, inside or outside current video memory. It +;; will be equally treated as video memory (taking into account CPC's video memory +;; disposition). This lets you copy software or hardware backbuffers, and +;; not only video memory. +;; * *sprite* must be an array containing sprite's pixels data in screen pixel format +;; * *width* must be the width of the screen to capture *in bytes*, and +;; must be 1 or more. Using 0 as *width* parameter for this function could potentially +;; make the program hang or crash. Always remember that the *width* must be +;; expressed in bytes and *not* in pixels. The correspondence is: +;; mode 0 - 1 byte = 2 pixels +;; modes 1 / 3 - 1 byte = 4 pixels +;; mode 2 - 1 byte = 8 pixels +;; * *height* must be the height of the sprite in bytes, and must be greater than 0. +;; There is no practical upper limit to this value. Height of a sprite in +;; bytes and pixels is the same value, as bytes only group consecutive pixels in +;; the horizontal space. +;; +;; Known limitations: +;; * This function does not do any kind of boundary check or clipping. If you +;; get data beyond your video memory or screen buffer the sprite will also contains +;; not video data. +;; +;; Details: +;; This function copies a video-memory location (either present video-memory or software / hardware +;; backbuffer) to a generic WxH bytes sprite from memory to . The destination sprite must be stored as an array (i.e. with +;; all of its pixels stored as consecutive bytes in memory). +;; +;; Destroyed Register values: +;; AF, BC, DE, HL +;; +;; Required memory: +;; C-bindings - 50 bytes +;; ASM-bindints - 44 bytes +;; +;; Time Measures: +;; (start code) +;; Case | microSecs (us) | CPU Cycles +;; ---------------------------------------------------------------- +;; Best | 16 + (27 + 12W)H | 84 + (88 + 72W)H +;; ---------------------------------------------------------------- +;; W=2,H=16 | 832 | 3328 +;; W=4,H=32 | 2416 | 9964 +;; ---------------------------------------------------------------- +;; Asm saving | -16 | -64 +;; ---------------------------------------------------------------- +;; (end code) +;; W = *width* in bytes, H = *height* in bytes +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + + push ix ;; [5] Save IX regiter before using it as temporal var + ld__ixl_c ;; [3] Save Sprite Width into IXL for later use + +dms_sprite_height_loop: + push de ;; [4] Save DE for later use (jump to next screen line) + +dms_sprite_width_loop: + ld a, (de) ;; [2] Get Screen byte into A + ld (hl), a ;; [2] Put A (Screen) byte into Sprite Memory + inc de ;; [2] Next Screen Memory byte + inc hl ;; [2] Next Sprite byte + + dec c ;; [1] C holds sprite width, we decrease it to count pixels in this line. + jr nz,dms_sprite_width_loop;; [2/3] While not 0, we are still painting this sprite line + ;; - When 0, we have to jump to next pixel line + + pop de ;; [3] Recover DE from stack. We use it to calculate start of next pixel line on screen + + dec b ;; [1] B holds sprite height. We decrease it to count another pixel line finished + jr z,dms_sprite_copy_ended;; [2/3] If 0, we have finished the last sprite line. + ;; - If not 0, we have to move pointers to the next pixel line + + ld__c_ixl ;; [3] Restore Sprite Width into C + + ld a, d ;; [1] Start of next pixel line normally is 0x0800 bytes away. + add #0x08 ;; [2] so we add it to DE (just by adding 0x08 to D) + ld d, a ;; [1] + and #0x38 ;; [2] We check if we have crossed memory boundary (every 8 pixel lines) + jr nz, dms_sprite_height_loop ;; [2/3] by checking the 4 bits that identify present memory line. + ;; .... If 0, we have crossed boundaries + +dms_sprite_8bit_boundary_crossed: + ld a, e ;; [1] DE = DE + 0xC050h + add #0x50 ;; [2] -- Relocate DE pointer to the start of the next pixel line: + ld e, a ;; [1] -- DE is moved forward 3 memory banks plus 50 bytes (4000h * 3) + ld a, d ;; [1] -- which effectively is the same as moving it 1 bank backwards and then + adc #0xC0 ;; [2] -- 50 bytes forwards (which is what we want to move it to the next pixel line) + ld d, a ;; [1] -- Calculations are made with 8 bit maths as it is faster than other alternatives here + + jr dms_sprite_height_loop ;; [3] Jump to continue with next pixel line + +dms_sprite_copy_ended: + pop ix ;; [5] Restore IX before returning + ret ;; [3] Return to caller diff --git a/cpctelera/src/video/cpct_getScreenToSprite_asmbindings.s b/cpctelera/src/video/cpct_getScreenToSprite_asmbindings.s new file mode 100644 index 000000000..46f4be8df --- /dev/null +++ b/cpctelera/src/video/cpct_getScreenToSprite_asmbindings.s @@ -0,0 +1,29 @@ +;;-----------------------------LICENSE NOTICE------------------------------------ +;; This file is part of CPCtelera: An Amstrad CPC Game Engine +;; Copyright (C) 2017 Arnaud Bouche +;; Copyright (C) 2015 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) +;; +;; This program is free software: you can redistribute it and/or modify +;; it under the terms of the GNU Lesser General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU Lesser General Public License for more details. +;; +;; You should have received a copy of the GNU Lesser General Public License +;; along with this program. If not, see <http://www.gnu.org/licenses/>. +;;------------------------------------------------------------------------------- +.module cpct_sprites + +;; Macros for easy use of undocumented opcodes +.include "../macros/cpct_undocumentedOpcodes.h.s" + +;; +;; ASM bindings for <cpct_getScreenToSprite> +;; +cpct_getScreenToSprite_asm:: ;; Assembly entry point + +.include /cpct_getScreenToSprite.asm/ \ No newline at end of file diff --git a/cpctelera/src/video/cpct_getScreenToSprite_cbindings.s b/cpctelera/src/video/cpct_getScreenToSprite_cbindings.s new file mode 100644 index 000000000..e6b778f3a --- /dev/null +++ b/cpctelera/src/video/cpct_getScreenToSprite_cbindings.s @@ -0,0 +1,39 @@ +;;-----------------------------LICENSE NOTICE------------------------------------ +;; This file is part of CPCtelera: An Amstrad CPC Game Engine +;; Copyright (C) 2017 Arnaud Bouche +;; Copyright (C) 2015 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) +;; +;; This program is free software: you can redistribute it and/or modify +;; it under the terms of the GNU Lesser General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU Lesser General Public License for more details. +;; +;; You should have received a copy of the GNU Lesser General Public License +;; along with this program. If not, see <http://www.gnu.org/licenses/>. +;;------------------------------------------------------------------------------- +.module cpct_sprites + +;; Macros for easy use of undocumented opcodes +.include "../macros/cpct_undocumentedOpcodes.h.s" + +;; +;; C bindings for <cpct_getScreenToSprite> +;; +;; 16 us, 5 bytes +;; +_cpct_getScreenToSprite:: + ;; GET Parameters from the stack + pop af ;; [3] AF = Return Address + pop de ;; [3] DE = Source Screen Address (Video memory location) + pop hl ;; [3] HL = Destination Sprite Address (Sprite data array) + pop bc ;; [3] BC = Height/Width (B = Height, C = Width) + + push af ;; [4] Put returning address in the stack again + ;; as this function uses __z88dk_callee convention + +.include /cpct_getScreenToSprite.asm/ \ No newline at end of file From f78f2b095310104e8dc4bb1e31a78835494c0c7f Mon Sep 17 00:00:00 2001 From: Arnaud <arnaud_bouche@hotmail.com> Date: Sat, 20 Jan 2018 12:44:04 +0100 Subject: [PATCH 08/31] Add screen capture example --- examples/medium/screenCapture/Makefile | 38 +++ .../medium/screenCapture/cfg/build_config.mk | 165 ++++++++++++ .../screenCapture/cfg/image_conversion.mk | 72 +++++ .../medium/screenCapture/img/building_1.png | Bin 0 -> 338 bytes .../medium/screenCapture/img/building_2.png | Bin 0 -> 276 bytes .../medium/screenCapture/img/building_3.png | Bin 0 -> 267 bytes examples/medium/screenCapture/img/ufo.png | Bin 0 -> 564 bytes examples/medium/screenCapture/src/main.c | 250 ++++++++++++++++++ 8 files changed, 525 insertions(+) create mode 100644 examples/medium/screenCapture/Makefile create mode 100644 examples/medium/screenCapture/cfg/build_config.mk create mode 100644 examples/medium/screenCapture/cfg/image_conversion.mk create mode 100644 examples/medium/screenCapture/img/building_1.png create mode 100644 examples/medium/screenCapture/img/building_2.png create mode 100644 examples/medium/screenCapture/img/building_3.png create mode 100644 examples/medium/screenCapture/img/ufo.png create mode 100644 examples/medium/screenCapture/src/main.c diff --git a/examples/medium/screenCapture/Makefile b/examples/medium/screenCapture/Makefile new file mode 100644 index 000000000..184f61b39 --- /dev/null +++ b/examples/medium/screenCapture/Makefile @@ -0,0 +1,38 @@ +##-----------------------------LICENSE NOTICE------------------------------------ +## This file is part of CPCtelera: An Amstrad CPC Game Engine +## Copyright (C) 2015 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) +## +## This program is free software: you can redistribute it and/or modify +## it under the terms of the GNU Lesser General Public License as published by +## the Free Software Foundation, either version 3 of the License, or +## (at your option) any later version. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU Lesser General Public License for more details. +## +## You should have received a copy of the GNU Lesser General Public License +## along with this program. If not, see <http://www.gnu.org/licenses/>. +##------------------------------------------------------------------------------ + +########################################################################### +## CPCTELERA ENGINE ## +## Main Building Makefile for Projects ## +##-----------------------------------------------------------------------## +## This file contains the rules for building a CPCTelera project. These ## +## These rules work generically for every CPCTelera project. ## +## Usually, this file should be left unchanged: ## +## * Project's build configuration is to be found in build_config.mk ## +## * Global paths and tool configuration is located at $(CPCT_PATH)/cfg/## +########################################################################### + +## +## PROJECT CONFIGURATION (you may change things there to setup this project) +## +include cfg/build_config.mk + +## +## USE GLOBAL MAKEFILE (general rules for building CPCtelera projects) +## +include $(CPCT_PATH)/cfg/global_main_makefile.mk diff --git a/examples/medium/screenCapture/cfg/build_config.mk b/examples/medium/screenCapture/cfg/build_config.mk new file mode 100644 index 000000000..2b1854740 --- /dev/null +++ b/examples/medium/screenCapture/cfg/build_config.mk @@ -0,0 +1,165 @@ +##-----------------------------LICENSE NOTICE------------------------------------ +## This file is part of CPCtelera: An Amstrad CPC Game Engine +## Copyright (C) 2015 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) +## +## This program is free software: you can redistribute it and/or modify +## it under the terms of the GNU Lesser General Public License as published by +## the Free Software Foundation, either version 3 of the License, or +## (at your option) any later version. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU Lesser General Public License for more details. +## +## You should have received a copy of the GNU Lesser General Public License +## along with this program. If not, see <http://www.gnu.org/licenses/>. +##------------------------------------------------------------------------------ + +########################################################################### +## CPCTELERA ENGINE ## +## Build configuration file ## +##-----------------------------------------------------------------------## +## This file is intendend for you to be able to config the way in which ## +## you would like to build this example of use of the CPCtelera Engine. ## +## Below you will find several configuration sections with the macros ## +## available to configure the build, along with explanation comments to ## +## help you understand what they do. Please, change everything you want. ## +########################################################################### + +## CPCTELERA MAIN PATH +## Sets CPCTelera main path for accessing tools and configuration. This +## variable must point to the folder where source and tools are contained. +## Setup creates and environment variable that will be generally used. +## However, when environment variable is not available, this variable +## should have the correct value for the project to compile. +## If you change folder structure, CPCT_PATH should reflect this change. +## This variable should always have the absolute path value. +## +#>> Uses environment variable $(CPCT_PATH) + +#### +## SECTION 1: Project configuration +## +## This section establishes source and object subfolders and the binary objects to +## be built. Normally, you want to change the OBJ files you want to be built, selecting +## only the ones that contain the actual code that will be used by you in your application. +##### + +# Name of the project (without spaces, as it will be used as filename) +# and Z80 memory location where code will start in the generated binary +PROJNAME := screenCapture +Z80CODELOC := 0x4000 + +## +## Folders +## +## SRCDIR = Source files for the project +## DSKFILESDIR = Input files to be added to the final DSK production +## OBJDIR = Object files generated on compilation +## +SRCDIR := src +DSKFILESDIR := dsk_files +OBJDIR := obj + +## +## File extensions +## +## C_EXT = C source files that will be automatically compiled +## ASM_EXT = ASM source files that will be automatically compiled +## BIN_EXT = Binary files that will be automatically converted to C source files for compilation +## OBJ_EXT = Object files generated after compilation +## DSKINC_EXT = Flag object files generated after file inclusion into DSK (to signal that a file has been included) +## +C_EXT := c +ASM_EXT := s +BIN_EXT := bin +OBJ_EXT := rel +DSKINC_EXT := dskinc + +## +## Output Binaries Configuration +## +## IHXFILE = Binary file that SDCC produces after compilation and linkage +## BINFILE = Binary file that is finally included in DSK and CDT (produced by Hex2Bin) +## CDT = CDT file produced +## DSK = DSK file produced +## DSKINC = Flag object file produced to signal DSK already has all include files in it +## +IHXFILE := $(OBJDIR)/$(PROJNAME).ihx +BINFILE := $(OBJDIR)/$(PROJNAME).bin +CDT := $(PROJNAME).cdt +DSK := $(PROJNAME).dsk +DSKINC := $(OBJDIR)/$(DSK).$(DSKINC_EXT) + +## +## TARGETs generated by Makefile: remove those you don't want to be generated +## +## $(CDT): Generates the CDT file with main binary +## $(DSK): Generates the DSK file with main binary +## $(DSKINC): Includes all files from DSKFILESDIR into DSK as binaries +## +TARGET := $(CDT) $(DSK) $(DSKINC) + +## +## OBJS2CLEAN: Additional objects to be removed when running "make clean" +## +OBJS2CLEAN := + +#### +## SECTION 2: TOOL PATH CONFIGURATION +## +## Paths are configured in the global_paths.mk configuration file included +## here. You may overwrite the values of path variables after the include +## if you wanted specific configuration for this project. +#### +include $(CPCT_PATH)/cfg/global_paths.mk + +#### +## SECTION 3: COMPILATION CONFIGURATION +## +## Flags used to configure the compilation of your code. They are usually +## fine for most of the projects, but you may change them for special uses. +##### +Z80CCFLAGS := +Z80ASMFLAGS := -l -o -s +Z80CCINCLUDE := -I$(CPCT_SRC) -I$(SRCDIR) +Z80CCLINKARGS := -mz80 --no-std-crt0 -Wl-u \ + --code-loc $(Z80CODELOC) \ + --data-loc 0 -l$(CPCT_LIB) +#### +## SECTION 4: CALCULATED FOLDERS, SUBFOLDERS AND FILES +## +## These macros calculate code subfolders, get all the source files and generate +## the corresponding subfolders and files in the object directory. All subfolders +## and files with source extension found are added, up to 1 level of depth in +## folder structure inside the main source directory. +#### +include $(CPCT_PATH)/cfg/global_functions.mk + +# Convert images and tilemaps +include cfg/image_conversion.mk + +# Calculate all subdirectories +SUBDIRS := $(filter-out ., $(shell find $(SRCDIR) -type d -print)) +OBJDSKINCSDIR := $(OBJDIR)/$(DSKFILESDIR) +OBJSUBDIRS := $(OBJDSKINCSDIR) $(foreach DIR, $(SUBDIRS), $(patsubst $(SRCDIR)%, $(OBJDIR)%, $(DIR))) + +# Calculate all source files +CFILES := $(foreach DIR, $(SUBDIRS), $(wildcard $(DIR)/*.$(C_EXT))) +CFILES := $(filter-out $(IMGCFILES), $(CFILES)) +ASMFILES := $(foreach DIR, $(SUBDIRS), $(wildcard $(DIR)/*.$(ASM_EXT))) +ASMFILES := $(filter-out $(IMGASMFILES), $(ASMFILES)) +BIN2CFILES := $(foreach DIR, $(SUBDIRS), $(wildcard $(DIR)/*.$(BIN_EXT))) +DSKINCSRCFILES := $(wildcard $(DSKFILESDIR)/*) + +# Calculate all object files +BIN_OBJFILES := $(patsubst %.$(BIN_EXT), %.$(C_EXT), $(BIN2CFILES)) +CFILES := $(filter-out $(BIN_OBJFILES), $(CFILES)) +GENC_OBJFILES := $(patsubst $(SRCDIR)%, $(OBJDIR)%, $(patsubst %.$(C_EXT), %.$(OBJ_EXT), $(IMGCFILES))) +GENASM_OBJFILES:= $(patsubst $(SRCDIR)%, $(OBJDIR)%, $(patsubst %.$(ASM_EXT), %.$(OBJ_EXT), $(IMGASMFILES))) +C_OBJFILES := $(patsubst $(SRCDIR)%, $(OBJDIR)%, $(patsubst %.$(C_EXT), %.$(OBJ_EXT), $(BIN_OBJFILES) $(CFILES))) +ASM_OBJFILES := $(patsubst $(SRCDIR)%, $(OBJDIR)%, $(patsubst %.$(ASM_EXT), %.$(OBJ_EXT), $(ASMFILES))) +DSKINCOBJFILES := $(foreach FILE, $(DSKINCSRCFILES), $(patsubst $(DSKFILESDIR)/%, $(OBJDSKINCSDIR)/%, $(FILE)).$(DSKINC_EXT)) +OBJFILES := $(C_OBJFILES) $(ASM_OBJFILES) +GENOBJFILES := $(GENC_OBJFILES) $(GENASM_OBJFILES) diff --git a/examples/medium/screenCapture/cfg/image_conversion.mk b/examples/medium/screenCapture/cfg/image_conversion.mk new file mode 100644 index 000000000..754e3b5d2 --- /dev/null +++ b/examples/medium/screenCapture/cfg/image_conversion.mk @@ -0,0 +1,72 @@ +##-----------------------------LICENSE NOTICE------------------------------------ +## This file is part of CPCtelera: An Amstrad CPC Game Engine +## Copyright (C) 2016 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) +## +## This program is free software: you can redistribute it and/or modify +## it under the terms of the GNU Lesser General Public License as published by +## the Free Software Foundation, either version 3 of the License, or +## (at your option) any later version. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU Lesser General Public License for more details. +## +## You should have received a copy of the GNU Lesser General Public License +## along with this program. If not, see <http://www.gnu.org/licenses/>. +##------------------------------------------------------------------------------ + +############################################################################ +## CPCTELERA ENGINE ## +## Automatic image conversion file ## +##------------------------------------------------------------------------## +## This file is intended for users to automate image conversion from JPG, ## +## PNG, GIF, etc. into C-arrays. ## +## ## +## Macro used for conversion is IMG2SPRITES, which has up to 9 parameters:## +## (1): Image file to be converted into C sprite (PNG, JPG, GIF, etc) ## +## (2): Graphics mode (0,1,2) for the generated C sprite ## +## (3): Prefix to add to all C-identifiers generated ## +## (4): Width in pixels of each sprite/tile/etc that will be generated ## +## (5): Height in pixels of each sprite/tile/etc that will be generated ## +## (6): Firmware palette used to convert the image file into C values ## +## (7): (mask / tileset /) ## +## - "mask": generate interlaced mask for all sprites converted ## +## - "tileset": generate a tileset array with pointers to all sprites ## +## (8): Output subfolder for generated .C/.H files (in project folder) ## +## (9): (hwpalette) ## +## - "hwpalette": output palette array with hardware colour values ## +## (10): Aditional options (you can use this to pass aditional modifiers ## +## to cpct_img2tileset) ## +## ## +## Macro is used in this way (one line for each image to be converted): ## +## $(eval $(call IMG2SPRITES,(1),(2),(3),(4),(5),(6),(7),(8),(9), (10))) ## +## ## +## Important: ## +## * Do NOT separate macro parameters with spaces, blanks or other chars.## +## ANY character you put into a macro parameter will be passed to the ## +## macro. Therefore ...,src/sprites,... will represent "src/sprites" ## +## folder, whereas ..., src/sprites,... means " src/sprites" folder. ## +## ## +## * You can omit parameters but leaving them empty. Therefore, if you ## +## wanted to specify an output folder but do not want your sprites to ## +## have mask and/or tileset, you may omit parameter (7) leaving it empty ## +## $(eval $(call IMG2SPRITES,imgs/1.png,0,g,4,8,$(PAL),,src/)) ## +############################################################################ + +## Example firmware palette definition as variable in cpct_img2tileset format + +PALETTE={13 1 2 3 6 9 10 11 15 19 20 21 24 25 26 0} + +## Example image conversion +## This example would convert img/example.png into src/example.{c|h} files. +## A C-array called pre_example[24*12*2] would be generated with the definition +## of the image example.png in mode 0 screen pixel format, with interlaced mask. +## The palette used for conversion is given through the PALETTE variable and +## a pre_palette[16] array will be generated with the 16 palette colours as +## hardware colour values. + +$(eval $(call IMG2SPRITES,img/ufo.png,0,g,32,0,$(PALETTE),mask,src/sprites,hwpalette)) +$(eval $(call IMG2SPRITES,img/building_1.png,0,g,0,0,$(PALETTE),,src/sprites,)) +$(eval $(call IMG2SPRITES,img/building_2.png,0,g,0,0,$(PALETTE),,src/sprites,)) +$(eval $(call IMG2SPRITES,img/building_3.png,0,g,0,0,$(PALETTE),,src/sprites,)) \ No newline at end of file diff --git a/examples/medium/screenCapture/img/building_1.png b/examples/medium/screenCapture/img/building_1.png new file mode 100644 index 0000000000000000000000000000000000000000..a5e0d14f1ce4b08e74c4399ba6ea046f6196ad30 GIT binary patch literal 338 zcmV-Y0j>UtP)<h;3K|Lk000e1NJLTq000&M004am1^@s7(SV~g00009a7bBm000XT z000XT0n*)m`~Uy}1W80eRCwC$n86OhAP_|NWa8N$_Otvj&#qaMH4Q1HR4Igg2hycL z7lvV&R4&(>dJ!r^S7;csL0->?TG6|x$5J=k0v~!{_$Rye$iB?#u>jo((0Smq*d%Th z%d?%A3*LG*o`!+7mNrG?Bs7e>9nmOlhEFdBH=rmKZNiOo2Rlh_ZYN`%?sQXPpYAU= zv@16T5t+{17)0xGTu9%?bOop=DvFAtqNwOEF842%xEXSXKJ5Qva&_aKb8k=oiJ_>i zPXxu<K?nkcDW9v~o~4$cnprC<p_&MaTA4&ExIxM+3M8AQ{`d;qCamBF!ENF;ahteJ kv;wz@+YI3=N=H5|Z`!N2$Q#LqiU0rr07*qoM6N<$f}|Ubi~s-t literal 0 HcmV?d00001 diff --git a/examples/medium/screenCapture/img/building_2.png b/examples/medium/screenCapture/img/building_2.png new file mode 100644 index 0000000000000000000000000000000000000000..574200112fc19a1885fa3d95b7d841bba483169a GIT binary patch literal 276 zcmeAS@N?(olHy`uVBq!ia0vp^d_bJe!N$PA=)T4IDv-lj;1OBOz`!j8!i<;h*8Kqr z9`kf@45_&FcA6nyg94AM^-PQE#QvuT=d69%;Hb-Wsi}oe#c64s+<YaT$1PVDygR&2 zPt_^!i%6y10m-1{Q+|3CJb0ntq)_x~Ld?$V8L9zM(JAUqx6hi#baVfz)|zpxTs$zu zLz|N^R6!!zcH8|X8LP%EcigyFhk9iT+<Ujxg@a>T>f2voE3cHij@C<!i~8HS<m;;I zik}SsI%r8YY}Vi2GCwHSW0mBBa%O`q+0qRkm&j^chov!yGMjwaom9H@?k*{&skVje Y2D+6d<z0syfj(mJboFyt=akR{03+yWE&u=k literal 0 HcmV?d00001 diff --git a/examples/medium/screenCapture/img/building_3.png b/examples/medium/screenCapture/img/building_3.png new file mode 100644 index 0000000000000000000000000000000000000000..235018de38c37333353be496377e1b3d6e763965 GIT binary patch literal 267 zcmV+m0rdWfP)<h;3K|Lk000e1NJLTq000sI002-31^@s7V_6lZ00009a7bBm000XT z000XT0n*)m`~Uy|y-7qtRCwC$R!ItgFbwQT@a%_umJjo6Trg6D#T1&@%78&r>ok*P zFm(MuY~fSK?jd=0^NWgwWu7QDn@?!F>`!qCESY#3!{O{OhfjB3kEGhfuxw7pUF=S_ z`AA5ncQV-|OCxqQ7dUnQS3fzi^U?y5JY#m~Omt?QomoW3i-nX0v=<^S2LErxZOGYt zdS5X$8EUTI5H)G2T8q@=EZRp@PDWlDuHmXdYB98sT1YLVR!i+|WYiJm0<CGJ6DiH^ RfR+FN002ovPDHLkV1lq)Yis}j literal 0 HcmV?d00001 diff --git a/examples/medium/screenCapture/img/ufo.png b/examples/medium/screenCapture/img/ufo.png new file mode 100644 index 0000000000000000000000000000000000000000..91af7df33e66ca7932259bc46add6cad398c5ae6 GIT binary patch literal 564 zcmV-40?Yl0P)<h;3K|Lk000e1NJLTq004jh000#T0ssI3cJM*^00009a7bBm000tn z000tn0p4aGcmMza=1D|BRCwC$SOJp5APC&2^K)8bh^S~tYA<$9$7XP|pivYoXe$6n zN?#5?W-#IX4Du%MfwSPkiAo%+M@~IDOX@ndOPNYM4M_}~$a)euRAG$5-*X!PgfXUP zsChHJt;jnkx1$6p%yA;hS=?}H;OG3zPqf>N!l6)RW{dq1F5XPL6Emg$4`lc011D&e z63^{4R<de(I1QDplcLJ^4#3kI6yK}x;1U+@;+t;3aiOAjpPvSg^2=?|DW<zW&QB*x zb%NL+x^E3IN6u9$ukWiM`ETe<p0z-%=V%^&u|?8rCYYvY<2TQ8&-R*uZ*HAEUe}?# zVf{%y>}=!EIh&`)`S|HGw2G7}703k3)AZYd%-rQ$iZ;JJB)!r3!nx}X7dt4+?^L-H zlz#pLj%e(tS@fQS@7F=K$)@1L)QP!$%lcIOD%&Q=b#4==7cv!Js+T{^KHR}vCFSHz z<*y_Q|I|LbnTV<bKV#XyvjA7Gw9Ed51(0Ja`$H(zK0<Kh#tl=xrprFv>cT&Ma!*Kw z+(^1t`GX<{7UzlY01&`fg9Vr$0mFOI^Ye{fmg~*n{bufc{DD`<{brKU4q3~7`y%7& zrWPDSU-nz};ps-=IH}++*V8LQci7J^jbE@o-S}T1uyE*q8gz;P0000<MNUMnLSTXu C(h#En literal 0 HcmV?d00001 diff --git a/examples/medium/screenCapture/src/main.c b/examples/medium/screenCapture/src/main.c new file mode 100644 index 000000000..bb2b7834f --- /dev/null +++ b/examples/medium/screenCapture/src/main.c @@ -0,0 +1,250 @@ +//-----------------------------LICENSE NOTICE------------------------------------ +// This file is part of CPCtelera: An Amstrad CPC Game Engine +// Copyright (C) 2017 Arnaud Bouche +// Copyright (C) 2015 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +//------------------------------------------------------------------------------ + +///////////////////////////////////////////////////////////////////////////////// +// INCLUDES +#include <cpctelera.h> + +///////////////////////////////////////////////////////////////////////////////// +// SPRITES +#include "sprites\ufo.h" +#include "sprites\building_1.h" +#include "sprites\building_2.h" +#include "sprites\building_3.h" + +///////////////////////////////////////////////////////////////////////////////// +// USEFUL MACROS AND CONSTANTS +// +#define BOOL u8 +#define TRUE 1 +#define FALSE 0 + +#define SCREEN_CY 200 +#define SCREEN_CX 80 +#define VMEM_SIZE 0x4000 + +#define UFO_Y 120 +#define UFO_INIT_X 0 +#define GRADIENT_CY 10 + +///////////////////////////////////////////////////////////////////////////////// +// GLOBAL VARIABLES +u8 gScreenCapture[G_UFO_0_H*G_UFO_0_W]; // Array of background capture of size of UFO + +///////////////////////////////////////////////////////////////////////////////// +// INITIALIZATION +// +void Initialization() +{ + cpct_disableFirmware(); + cpct_setVideoMode(0); // Set mode 0 + cpct_setPalette (g_palette, 16); // Set the palette + cpct_setBorder(0x14); // Set the border color with Hardware color (Black) + + // Fill screen with color index 4 (Red) + cpct_memset(CPCT_VMEM_START, cpct_px2byteM0(4, 4), VMEM_SIZE); +} + +///////////////////////////////////////////////////////////////////////////////// +// GET UFO CURRENT ANIMATION SPRITE +// +u8* GetUfoSprite() +{ + // Current animation state + static u8 anim = 0; + + // Array of all four sprites of UFO + static u8* const ufoSprite[] = { g_ufo_0, g_ufo_1, g_ufo_2, g_ufo_3 }; + + // Get next animation sprite and return it + return ufoSprite[anim++ % 4]; +} + +///////////////////////////////////////////////////////////////////////////////// +// DRAW UFO +// +void DrawUFO() +{ + static BOOL moveRight; // Keep move direction + static u8 posX; // Keep position X + + u8* pvmem; + + // Get VMem pointer of current UFO position for background replacement + u8* backPmem = cpct_getScreenPtr(CPCT_VMEM_START, posX, UFO_Y); + + // Move to right or to left + // If border is reached go to opposite direction + if (moveRight == FALSE) + { + // If left border reached go to right border + if (posX == 0) + moveRight = TRUE; // Change direction + else + posX--; // Move to left + } + else + { + // If right border reached go to left border + if (posX == SCREEN_CX - G_UFO_0_W - 1) + moveRight = FALSE; // Change direction + else + posX++; // Move to right + } + + // Get VMem pointer of new UFO position + pvmem = cpct_getScreenPtr(CPCT_VMEM_START, posX, UFO_Y); + + // Wait for VSync and draw background and UFO + // This drawing operation is fast enough not to be caught by the raster, and does not produce + // any flickering. In other case you have to use double-buffer to prevent this. + cpct_waitVSYNC(); + + // Replace background with previous position + cpct_drawSprite(gScreenCapture, backPmem, G_UFO_0_W, G_UFO_0_H); + + // Memorize current background for next move + cpct_getScreenToSprite(pvmem, gScreenCapture, G_UFO_0_W, G_UFO_0_H); + + // Draw UFO over background redrawn + cpct_drawSpriteMasked(GetUfoSprite(), pvmem, G_UFO_0_W, G_UFO_0_H); +} + +///////////////////////////////////////////////////////////////////////////////// +// FILL LINE OF COLOR +// +void FillLine(u8 pixColor, u8 lineY) +{ + // Get line start at line Y position + u8* pvmem = cpct_getScreenPtr(CPCT_VMEM_START, 0, lineY); + + // Fill screen line width with color + cpct_memset(pvmem, pixColor, SCREEN_CX); +} + +///////////////////////////////////////////////////////////////////////////////// +// DRAW SKY PART FILLED WITH GRADIANT +// +u8 DrawSkyGradiant(u8 cy, u8 posY, u8 colorFront, u8 colorBack) +{ + u8 i, j; + + // Get byte color M0 for front color + u8 pixFront = cpct_px2byteM0(colorFront, colorFront); + + // Get byte color M0 for back color + u8 pixBack = cpct_px2byteM0(colorBack, colorBack); + + // Draw gradiant zone + for (j = 0; j < cy; j++) + { + // If end of screen reached stop drawing + if (posY == SCREEN_CY - 2) + break; + + // Draw lines of color + for (i = 0; i < cy - j; i++) + { + FillLine(pixFront, posY++); + } + FillLine(pixBack, posY++); + } + + // Return ending line colorized + return posY; +} + +///////////////////////////////////////////////////////////////////////////////// +// DRAW SKY WITH GRADIENT ZONES FOR BACKGROUND +// +void DrawSky() +{ + // Define color of gradient sky parts + const u8 colors[] = { 2, 15, 2, 7, 10, 13, 8, 4 }; + + // Current line filled with color + u8 startLine = 0; + + // Screen is divided into gradient zone + u8 i; + for (i = 1; i < sizeof(colors); i++) + startLine = DrawSkyGradiant(GRADIENT_CY - i, startLine, colors[i], colors[i - 1]); +} + +///////////////////////////////////////////////////////////////////////////////// +// DRAW CITY WITH ALL BUILDING FOR BACKGROUND +// +void DrawCity() +{ + u8* pvmem = cpct_getScreenPtr(CPCT_VMEM_START, 10, SCREEN_CY - G_BUILDING_1_H); + cpct_drawSprite(g_building_1, pvmem, G_BUILDING_1_W, G_BUILDING_1_H); + + pvmem = cpct_getScreenPtr(CPCT_VMEM_START, 30, SCREEN_CY - G_BUILDING_2_H); + cpct_drawSprite(g_building_2, pvmem, G_BUILDING_2_W, G_BUILDING_2_H); + + pvmem = cpct_getScreenPtr(CPCT_VMEM_START, 40, SCREEN_CY - G_BUILDING_1_H); + cpct_drawSprite(g_building_1, pvmem, G_BUILDING_1_W, G_BUILDING_1_H); + + pvmem = cpct_getScreenPtr(CPCT_VMEM_START, 67, SCREEN_CY - G_BUILDING_2_H); + cpct_drawSprite(g_building_2, pvmem, G_BUILDING_2_W, G_BUILDING_2_H); + + pvmem = cpct_getScreenPtr(CPCT_VMEM_START, 60, SCREEN_CY - G_BUILDING_3_H); + cpct_drawSprite(g_building_3, pvmem, G_BUILDING_3_W, G_BUILDING_3_H); +} + +///////////////////////////////////////////////////////////////////////////////// +// INITIALIZE FIRST BACKGROUND CAPTURE +// +void InitCapture() +{ + // Get VMem pointer of default UFO position + u8* pvmem = cpct_getScreenPtr(CPCT_VMEM_START, UFO_INIT_X, UFO_Y); + + // Capture first UFO background + cpct_getScreenToSprite(pvmem, gScreenCapture, G_UFO_0_W, G_UFO_0_H); +} + +///////////////////////////////////////////////////////////////////////////////// +// DRAW BACKGROUND WITH GRADIENT SKY AND BUILDING +// +void DrawBackground() +{ + DrawSky(); + DrawCity(); + + InitCapture(); +} + +/////////////////////////////////////////////////////// +/// MAIN PROGRAM +/// +void main(void) +{ + // Initialize everything + Initialization(); + + // Draw background with sky and buildings + DrawBackground(); + + // Main Loop + while(1) + { + DrawUFO(); + } +} From bfbada123f86b9d731dec6f2e594423290ee9dfe Mon Sep 17 00:00:00 2001 From: Arnaud <arnaud_bouche@hotmail.com> Date: Sat, 20 Jan 2018 12:46:47 +0100 Subject: [PATCH 09/31] Remove useless files in example --- .../src/asm/macros/cpct_reverseBits.s | 263 ------------------ .../src/asm/macros/cpct_undocumentedOpcodes.s | 97 ------- .../M0/cpct_drawSpriteColorizeM0.asm | 203 -------------- .../cpct_drawSpriteColorizeM0_asmbindings.s | 36 --- .../M0/cpct_drawSpriteColorizeM0_cbindings.s | 48 ---- ...cpct_drawSpriteMaskedAlignedColorizeM0.asm | 215 -------------- ...priteMaskedAlignedColorizeM0_asmbindings.s | 36 --- ...wSpriteMaskedAlignedColorizeM0_cbindings.s | 52 ---- .../M0/cpct_drawSpriteMaskedColorizeM0.asm | 216 -------------- ...t_drawSpriteMaskedColorizeM0_asmbindings.s | 36 --- ...pct_drawSpriteMaskedColorizeM0_cbindings.s | 48 ---- .../colorReplace/M0/cpct_spriteColorizeM0.asm | 166 ----------- .../M0/cpct_spriteColorizeM0_asmbindings.s | 36 --- .../M0/cpct_spriteColorizeM0_cbindings.s | 48 ---- .../M0/cpct_spriteMaskedColorizeM0.asm | 175 ------------ .../cpct_spriteMaskedColorizeM0_asmbindings.s | 36 --- .../cpct_spriteMaskedColorizeM0_cbindings.s | 48 ---- .../M1/cpct_drawSpriteColorizeM1.asm | 228 --------------- .../cpct_drawSpriteColorizeM1_asmbindings.s | 35 --- .../M1/cpct_drawSpriteColorizeM1_cbindings.s | 48 ---- ...cpct_drawSpriteMaskedAlignedColorizeM1.asm | 239 ---------------- ...priteMaskedAlignedColorizeM1_asmbindings.s | 36 --- ...wSpriteMaskedAlignedColorizeM1_cbindings.s | 53 ---- .../M1/cpct_drawSpriteMaskedColorizeM1.asm | 246 ---------------- ...t_drawSpriteMaskedColorizeM1_asmbindings.s | 36 --- ...pct_drawSpriteMaskedColorizeM1_cbindings.s | 48 ---- .../colorReplace/M1/cpct_spriteColorizeM1.asm | 194 ------------- .../M1/cpct_spriteColorizeM1_asmbindings.s | 35 --- .../M1/cpct_spriteColorizeM1_cbindings.s | 48 ---- .../M1/cpct_spriteMaskedColorizeM1.asm | 205 -------------- .../cpct_spriteMaskedColorizeM1_asmbindings.s | 36 --- .../cpct_spriteMaskedColorizeM1_cbindings.s | 48 ---- .../medium/colorReplace/src/sprites/baloon.c | 43 --- .../medium/colorReplace/src/sprites/baloon.h | 12 - .../colorReplace/src/sprites/circle_trans.c | 12 - .../colorReplace/src/sprites/circle_trans.h | 10 - .../medium/colorReplace/src/sprites/cloud.c | 60 ---- .../medium/colorReplace/src/sprites/cloud.h | 10 - .../medium/colorReplace/src/sprites/roof.c | 26 -- .../medium/colorReplace/src/sprites/roof.h | 10 - .../colorReplace/src/sprites/sprites_gen.txt | 0 .../medium/colorReplace/src/sprites/square.c | 12 - .../medium/colorReplace/src/sprites/square.h | 10 - .../colorReplace/src/sprites/star_trans.c | 12 - .../colorReplace/src/sprites/star_trans.h | 10 - 45 files changed, 3521 deletions(-) delete mode 100644 examples/medium/colorReplace/src/asm/macros/cpct_reverseBits.s delete mode 100644 examples/medium/colorReplace/src/asm/macros/cpct_undocumentedOpcodes.s delete mode 100644 examples/medium/colorReplace/src/asm/sprites/colorReplace/M0/cpct_drawSpriteColorizeM0.asm delete mode 100644 examples/medium/colorReplace/src/asm/sprites/colorReplace/M0/cpct_drawSpriteColorizeM0_asmbindings.s delete mode 100644 examples/medium/colorReplace/src/asm/sprites/colorReplace/M0/cpct_drawSpriteColorizeM0_cbindings.s delete mode 100644 examples/medium/colorReplace/src/asm/sprites/colorReplace/M0/cpct_drawSpriteMaskedAlignedColorizeM0.asm delete mode 100644 examples/medium/colorReplace/src/asm/sprites/colorReplace/M0/cpct_drawSpriteMaskedAlignedColorizeM0_asmbindings.s delete mode 100644 examples/medium/colorReplace/src/asm/sprites/colorReplace/M0/cpct_drawSpriteMaskedAlignedColorizeM0_cbindings.s delete mode 100644 examples/medium/colorReplace/src/asm/sprites/colorReplace/M0/cpct_drawSpriteMaskedColorizeM0.asm delete mode 100644 examples/medium/colorReplace/src/asm/sprites/colorReplace/M0/cpct_drawSpriteMaskedColorizeM0_asmbindings.s delete mode 100644 examples/medium/colorReplace/src/asm/sprites/colorReplace/M0/cpct_drawSpriteMaskedColorizeM0_cbindings.s delete mode 100644 examples/medium/colorReplace/src/asm/sprites/colorReplace/M0/cpct_spriteColorizeM0.asm delete mode 100644 examples/medium/colorReplace/src/asm/sprites/colorReplace/M0/cpct_spriteColorizeM0_asmbindings.s delete mode 100644 examples/medium/colorReplace/src/asm/sprites/colorReplace/M0/cpct_spriteColorizeM0_cbindings.s delete mode 100644 examples/medium/colorReplace/src/asm/sprites/colorReplace/M0/cpct_spriteMaskedColorizeM0.asm delete mode 100644 examples/medium/colorReplace/src/asm/sprites/colorReplace/M0/cpct_spriteMaskedColorizeM0_asmbindings.s delete mode 100644 examples/medium/colorReplace/src/asm/sprites/colorReplace/M0/cpct_spriteMaskedColorizeM0_cbindings.s delete mode 100644 examples/medium/colorReplace/src/asm/sprites/colorReplace/M1/cpct_drawSpriteColorizeM1.asm delete mode 100644 examples/medium/colorReplace/src/asm/sprites/colorReplace/M1/cpct_drawSpriteColorizeM1_asmbindings.s delete mode 100644 examples/medium/colorReplace/src/asm/sprites/colorReplace/M1/cpct_drawSpriteColorizeM1_cbindings.s delete mode 100644 examples/medium/colorReplace/src/asm/sprites/colorReplace/M1/cpct_drawSpriteMaskedAlignedColorizeM1.asm delete mode 100644 examples/medium/colorReplace/src/asm/sprites/colorReplace/M1/cpct_drawSpriteMaskedAlignedColorizeM1_asmbindings.s delete mode 100644 examples/medium/colorReplace/src/asm/sprites/colorReplace/M1/cpct_drawSpriteMaskedAlignedColorizeM1_cbindings.s delete mode 100644 examples/medium/colorReplace/src/asm/sprites/colorReplace/M1/cpct_drawSpriteMaskedColorizeM1.asm delete mode 100644 examples/medium/colorReplace/src/asm/sprites/colorReplace/M1/cpct_drawSpriteMaskedColorizeM1_asmbindings.s delete mode 100644 examples/medium/colorReplace/src/asm/sprites/colorReplace/M1/cpct_drawSpriteMaskedColorizeM1_cbindings.s delete mode 100644 examples/medium/colorReplace/src/asm/sprites/colorReplace/M1/cpct_spriteColorizeM1.asm delete mode 100644 examples/medium/colorReplace/src/asm/sprites/colorReplace/M1/cpct_spriteColorizeM1_asmbindings.s delete mode 100644 examples/medium/colorReplace/src/asm/sprites/colorReplace/M1/cpct_spriteColorizeM1_cbindings.s delete mode 100644 examples/medium/colorReplace/src/asm/sprites/colorReplace/M1/cpct_spriteMaskedColorizeM1.asm delete mode 100644 examples/medium/colorReplace/src/asm/sprites/colorReplace/M1/cpct_spriteMaskedColorizeM1_asmbindings.s delete mode 100644 examples/medium/colorReplace/src/asm/sprites/colorReplace/M1/cpct_spriteMaskedColorizeM1_cbindings.s delete mode 100644 examples/medium/colorReplace/src/sprites/baloon.c delete mode 100644 examples/medium/colorReplace/src/sprites/baloon.h delete mode 100644 examples/medium/colorReplace/src/sprites/circle_trans.c delete mode 100644 examples/medium/colorReplace/src/sprites/circle_trans.h delete mode 100644 examples/medium/colorReplace/src/sprites/cloud.c delete mode 100644 examples/medium/colorReplace/src/sprites/cloud.h delete mode 100644 examples/medium/colorReplace/src/sprites/roof.c delete mode 100644 examples/medium/colorReplace/src/sprites/roof.h create mode 100644 examples/medium/colorReplace/src/sprites/sprites_gen.txt delete mode 100644 examples/medium/colorReplace/src/sprites/square.c delete mode 100644 examples/medium/colorReplace/src/sprites/square.h delete mode 100644 examples/medium/colorReplace/src/sprites/star_trans.c delete mode 100644 examples/medium/colorReplace/src/sprites/star_trans.h diff --git a/examples/medium/colorReplace/src/asm/macros/cpct_reverseBits.s b/examples/medium/colorReplace/src/asm/macros/cpct_reverseBits.s deleted file mode 100644 index 35c643fde..000000000 --- a/examples/medium/colorReplace/src/asm/macros/cpct_reverseBits.s +++ /dev/null @@ -1,263 +0,0 @@ -;;-----------------------------LICENSE NOTICE------------------------------------ -;; This file is part of CPCtelera: An Amstrad CPC Game Engine -;; Copyright (C) 2016 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) -;; -;; This program is free software: you can redistribute it and/or modify -;; it under the terms of the GNU Lesser General Public License as published by -;; the Free Software Foundation, either version 3 of the License, or -;; (at your option) any later version. -;; -;; This program is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU Lesser General Public License for more details. -;; -;; You should have received a copy of the GNU Lesser General Public License -;; along with this program. If not, see <http://www.gnu.org/licenses/>. -;;------------------------------------------------------------------------------- - -;; -;; File: Reverse Bits -;; -;; Useful macros for bit reversing and selecting in different ways. Only -;; valid to be used from assembly language (not from C). -;; - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; Macro: cpctm_reverse_and_select_bits_of_A -;; -;; Reorders the bits of A and mixes them letting the user select the -;; new order for the bits by using a selection mask. -;; -;; Parameters: -;; TReg - An 8-bits register that will be used for intermediate calculations. -;; This register may be one of these: B, C, D, E, H, L -;; SelectionMask - An 8-bits mask that will be used to select the bits to get from -;; the reordered bits. It might be an 8-bit register or even (hl). -;; -;; Input Registers: -;; A - Byte to be reversed -;; TReg - Should have a copy of A (same exact value) -;; -;; Return Value: -;; A - Resulting value with bits reversed and selected -;; -;; Details: -;; This macro reorders the bits in A and mixes them with the same bits in -;; their original order by using a *SelectionMask*. The process is as follows: -;; -;; 1. Consider the 8 bits of A = TReg = [01234567] -;; 2. Reorder the 8 bits of A, producing A2 = [32547610] -;; 2. Reorder the bits of TReg, producing TReg2 = [76103254] -;; 3. Combines both reorders into final result using a *SelectionMask*. Each -;; 0 bit from the selection mask means "select bit from A2", whereas each 1 bit -;; means "select bit from TReg2". -;; -;; For instance, a selection mask 0b11001100 will produce this result: -;; -;; (start code) -;; A2 = [ 32 54 76 10 ] -;; TReg2 = [ 76 10 32 54 ] -;; SelMask = [ 11 00 11 00 ] // 1 = TReg2-bits, 0 = A2-bits -;; --------------------------- -;; Result = [ 76 54 32 10 ] -;; (end code) -;; -;; Therefore, mask 0b11001100 produces the effect of reversing the bits of A -;; completely. Other masks will produce different reorders of the bits in A, for -;; different requirements or needs. -;; -;; Modified Registers: -;; AF, TReg -;; -;; Required memory: -;; 16 bytes -;; -;; Time Measures: -;; (start code) -;; Case | microSecs(us) | CPU Cycles -;; ------------------------------------ -;; Any | 16 | 64 -;; ------------------------------------ -;; (end code) -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -.macro cpctm_reverse_and_select_bits_of_A TReg, SelectionMask - rlca ;; [1] | Rotate left twice so that... - rlca ;; [1] | ... A=[23456701] - - ;; Mix bits of TReg and A so that all bits are in correct relative order - ;; but displaced from their final desired location - xor TReg ;; [1] TReg = [01234567] (original value) - and #0b01010101 ;; [2] A = [23456701] (bits rotated twice left) - xor TReg ;; [1] A2 = [03254761] (TReg mixed with A to get bits in order) - - ;; Now get bits 54 and 10 in their right location and save them into TReg - rlca ;; [1] A = [ 32 54 76 10 ] (54 and 10 are in their desired place) - ld TReg, a ;; [1] TReg = A (Save this bit location into TReg) - - ;; Now get bits 76 and 32 in their right location in A - rrca ;; [1] | Rotate A right 4 times to... - rrca ;; [1] | ... get bits 76 and 32 located at their ... - rrca ;; [1] | ... desired location : - rrca ;; [1] | ... A = [ 76 10 32 54 ] (76 and 32 are in their desired place) - - ;; Finally, mix bits from TReg and A to get all bits reversed and selected - xor TReg ;; [1] TReg = [32547610] (Mixed bits with 54 & 10 in their right place) - and SelectionMask ;; [2] A = [76103254] (Mixed bits with 76 & 32 in their right place) - xor TReg ;; [1] A2 = [xxxxxxxx] final value: bits of A reversed and selected using *SelectionMask* -.endm - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; Macro: cpctm_reverse_bits_of_A -;; Macro: cpctm_reverse_mode_2_pixels_of_A -;; -;; Reverses the 8-bits of A, from [01234567] to [76543210]. This also reverses -;; all pixels contained in A when A is in screen pixel format, mode 2. -;; -;; Parameters: -;; TReg - An 8-bits register that will be used for intermediate calculations. -;; This register may be one of these: B, C, D, E, H, L -;; -;; Input Registers: -;; A - Byte to be reversed -;; TReg - Should have a copy of A (same exact value) -;; -;; Return Value: -;; A - Resulting value with bits reversed -;; -;; Requires: -;; - Uses the macro <cpctm_reverse_and_select_bits_of_A>. -;; -;; Details: -;; This macro reverses the bits in A. If bits of A = [01234567], the final -;; result after processing this macro will be A = [76543210]. Register TReg is -;; used for intermediate calculations and its value is destroyed. -;; -;; Modified Registers: -;; AF, TReg -;; -;; Required memory: -;; 16 bytes -;; -;; Time Measures: -;; (start code) -;; Case | microSecs(us) | CPU Cycles -;; ------------------------------------ -;; Any | 16 | 64 -;; ------------------------------------ -;; (end code) -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -.macro cpctm_reverse_bits_of_A TReg - cpctm_reverse_and_select_bits_of_A TReg, #0b11001100 -.endm -.macro cpctm_reverse_mode_2_pixels_of_A TReg - cpctm_reverse_bits_of_A TReg -.endm - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; Macro: cpctm_reverse_mode_1_pixels_of_A -;; -;; Reverses the order of pixel values contained in register A, assuming A is -;; in screen pixel format, mode 1. -;; -;; Parameters: -;; TReg - An 8-bits register that will be used for intermediate calculations. -;; This register may be one of these: B, C, D, E, H, L -;; -;; Input Registers: -;; A - Byte with pixel values to be reversed -;; TReg - Should have a copy of A (same exact value) -;; -;; Return Value: -;; A - Resulting byte with the 4 pixels values reversed in order -;; -;; Requires: -;; - Uses the macro <cpctm_reverse_and_select_bits_of_A>. -;; -;; Details: -;; This macro considers that A contains a byte that codifies 4 pixels in -;; screen pixel format, mode 1. It modifies A to reverse the order of its 4 -;; contained pixel values left-to-right (1234 -> 4321). With respect to the -;; order of the 8-bits of A, the concrete operations performed is: -;; (start code) -;; A = [012345678] == reverse-pixels ==> [10326587] = A2 -;; (end code) -;; You may want to check <cpct_px2byteM1> to know how bits codify both pixels -;; in one single byte for screen pixel format, mode 1. -;; -;; *TReg* is an 8-bit register that will be used for intermediate calculations, -;; destroying its original value (that should be same as A, at the start). -;; -;; Modified Registers: -;; AF, TReg -;; -;; Required memory: -;; 16 bytes -;; -;; Time Measures: -;; (start code) -;; Case | microSecs(us) | CPU Cycles -;; ------------------------------------ -;; Any | 16 | 64 -;; ------------------------------------ -;; (end code) -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -.macro cpctm_reverse_mode_1_pixels_of_A TReg - cpctm_reverse_and_select_bits_of_A TReg, #0b00110011 -.endm - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; Macro: cpctm_reverse_mode_0_pixels_of_A -;; -;; Reverses the order of pixel values contained in register A, assuming A is -;; in screen pixel format, mode 0. -;; -;; Parameters: -;; TReg - An 8-bits register that will be used for intermediate calculations. -;; This register may be one of these: B, C, D, E, H, L -;; -;; Input Registers: -;; A - Byte with pixel values to be reversed -;; TReg - Should have a copy of A (same exact value) -;; -;; Return Value: -;; A - Resulting byte with the 2 pixels values reversed in order -;; -;; Details: -;; This macro considers that A contains a byte that codifies 2 pixels in -;; screen pixel format, mode 0. It modifies A to reverse the order of its 2 -;; contained pixel values left-to-right (12 -> 21). With respect to the -;; order of the 8-bits of A, the concrete operation performed is: -;; (start code) -;; A = [012345678] == reverse-pixels ==> [10325476] = A2 -;; (end code) -;; You may want to check <cpct_px2byteM0> to know how bits codify both pixels -;; in one single byte for screen pixel format, mode 0. -;; -;; *TReg* is an 8-bit register that will be used for intermediate calculations, -;; destroying its original value (that should be same as A, at the start). -;; -;; Modified Registers: -;; AF, TReg -;; -;; Required memory: -;; 7 bytes -;; -;; Time Measures: -;; (start code) -;; Case | microSecs(us) | CPU Cycles -;; ------------------------------------ -;; Any | 7 | 28 -;; ------------------------------------ -;; (end code) -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -.macro cpctm_reverse_mode_0_pixels_of_A TReg - rlca ;; [1] | Rotate A twice to the left to get bits ordered... - rlca ;; [1] | ... in the way we need for mixing, A = [23456701] - - ;; Mix TReg with A to get pixels reversed by reordering bits - xor TReg ;; [1] | TReg = [01234567] - and #0b01010101 ;; [2] | A = [23456701] - xor TReg ;; [1] | A2 = [03254761] - rrca ;; [1] Rotate right to get pixels reversed A = [10325476] -.endm \ No newline at end of file diff --git a/examples/medium/colorReplace/src/asm/macros/cpct_undocumentedOpcodes.s b/examples/medium/colorReplace/src/asm/macros/cpct_undocumentedOpcodes.s deleted file mode 100644 index 258e16fbd..000000000 --- a/examples/medium/colorReplace/src/asm/macros/cpct_undocumentedOpcodes.s +++ /dev/null @@ -1,97 +0,0 @@ -;;-----------------------------LICENSE NOTICE------------------------------------ -;; This file is part of CPCtelera: An Amstrad CPC Game Engine -;; Copyright (C) 2016 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) -;; -;; This program is free software: you can redistribute it and/or modify -;; it under the terms of the GNU Lesser General Public License as published by -;; the Free Software Foundation, either version 3 of the License, or -;; (at your option) any later version. -;; -;; This program is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU Lesser General Public License for more details. -;; -;; You should have received a copy of the GNU Lesser General Public License -;; along with this program. If not, see <http://www.gnu.org/licenses/>. -;;------------------------------------------------------------------------------- - -;; -;; File: Undocumented Opcodes -;; -;; Macros to clarify source code when using undocumented opcodes. Only -;; valid to be used from assembly language (not from C). -;; - -;; Macro: jr__0 -;; Opcode for "JR #0" instruction -;; -.macro jr__0 - .DW #0x0018 ;; JR #00 (Normally used as a modifiable jump, as jr 0 is an infinite loop) -.endm - -;; Macro: ld__ixl_c -;; Opcode for "LD IXL, C" instruction -;; -.macro ld__ixl_c - .DW #0x69DD ;; ld ixl, c -.endm - -;; Macro: ld__c_ixl -;; Opcode for "LD C, IXL" instruction -;; -.macro ld__c_ixl - .DW #0x4DDD ;; ld c, ixl -.endm - -;; Macro: ld__ixl_b -;; Opcode for "LD IXL, B" instruction -;; -.macro ld__ixl_b - .DW #0x68DD ;; ld ixl, b -.endm - -;; Macro: ld__b_ixl -;; Opcode for "LD B, IXL" instruction -;; -.macro ld__b_ixl - .DW #0x45DD ;; ld b, ixl -.endm - -;; Macro: ld__a_ixl -;; Opcode for "LD A, IXL" instruction -;; -.macro ld__a_ixl - .dw #0x7DDD ;; Opcode for ld a, ixl -.endm - -;; Macro: ld__ixl_a -;; Opcode for "LD IXL, A" instruction -;; -.macro ld__ixl_a - .dw #0x6FDD ;; Opcode for ld ixl, a -.endm - -;; Macro: dec__ixh -;; Opcode for "DEC IXH" instruction -;; -.macro dec__ixh - .dw #0x25DD ;; Opcode for dec ixh -.endm - -;; Macro: dec__ixl -;; Opcode for "DEC IXL" instruction -;; -.macro dec__ixl - .dw #0x2DDD ;; Opcode for dec ixl -.endm - -;; Macro: ld__ixl Value -;; Opcode for "LD IXL, Value" instruction -;; -;; Parameters: -;; Value - An inmediate 8-bits value that will be loaded into IXL -;; -.macro ld__ixl Value - .db #0xDD, #0x2E, Value ;; Opcode for ld ixl, Value -.endm diff --git a/examples/medium/colorReplace/src/asm/sprites/colorReplace/M0/cpct_drawSpriteColorizeM0.asm b/examples/medium/colorReplace/src/asm/sprites/colorReplace/M0/cpct_drawSpriteColorizeM0.asm deleted file mode 100644 index 01cb1f2b5..000000000 --- a/examples/medium/colorReplace/src/asm/sprites/colorReplace/M0/cpct_drawSpriteColorizeM0.asm +++ /dev/null @@ -1,203 +0,0 @@ -;;-----------------------------LICENSE NOTICE------------------------------------ -;; This file is part of CPCtelera: An Amstrad CPC Game Engine -;; Copyright (C) 2017 Arnaud Bouche (Arnaud6128) -;; Copyright (C) 2017 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) -;; -;; This program is free software: you can redistribute it and/or modify -;; it under the terms of the GNU Lesser General Public License as published by -;; the Free Software Foundation, either version 3 of the License, or -;; (at your option) any later version. -;; -;; This program is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU Lesser General Public License for more details. -;; -;; You should have received a copy of the GNU Lesser General Public License -;; along with this program. If not, see <http://www.gnu.org/licenses/>. -;;------------------------------------------------------------------------------- -.module cpct_sprites - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; -;; Function: cpct_drawSpriteColorizeM0 -;; -;; Directly replace a color and draw a sprite to video memory. -;; -;; C Definition: -;; void <cpct_drawSpriteColorizeM0> (void* *sprite*, void* *memory*, <u8> *width*, <u8> *height*, <u8> *oldColor*, <u8> *newColor*) __z88dk_callee; -;; -;; Input Parameters (8 bytes): -;; (2B HL') sprite - Source Sprite Pointer (array of pixel data) -;; (2B DE') memory - Destination video memory pointer -;; (1B C' ) height - Sprite Height in bytes (>0) -;; (1B B' ) width - Sprite Width in *bytes* (Beware, *not* in pixels!) -;; (1B L ) oldColor - Color to replace -;; (1B H ) newColor - New color -;; -;; Assembly call (Input parameters on registers): -;; > call cpct_drawSpriteColorizeM0_asm -;; -;; Parameter Restrictions: -;; * *sprite* must be an array containing sprite's pixels data in screen pixel format. -;; Sprite must be rectangular and all bytes in the array must be consecutive pixels, -;; starting from top-left corner and going left-to-right, top-to-bottom down to the -;; bottom-right corner. Total amount of bytes in pixel array should be *width* x *height*. -;; * *memory* could be any place in memory, inside or outside current video memory. It -;; will be equally treated as video memory (taking into account CPC's video memory -;; disposition). This lets you copy sprites to software or hardware backbuffers, and -;; not only video memory. -;; * *width* must be the width of the sprite *in bytes*. Always remember that the width must be -;; expressed in bytes and *not* in pixels. -;; The correspondence is mode 0 : 1 byte = 2 pixels -;; * *height* must be the height of the sprite in bytes, and must be greater than 0. -;; There is no practical upper limit to this value. Height of a sprite in -;; bytes and pixels is the same value, as bytes only group consecutive pixels in -;; the horizontal space. -;; * *oldColor* must be the index of color (0 to 15) to replace -;; * *newColor* must be the index of the new color (0 to 15) -;; -;; Known limitations: -;; * This function does not do any kind of boundary check or clipping. If you -;; try to draw sprites on the frontier of your video memory or screen buffer -;; if might potentially overwrite memory locations beyond boundaries. This -;; could cause your program to behave erratically, hang or crash. Always -;; take the necessary steps to guarantee that you are drawing inside screen -;; or buffer boundaries. -;; * As this function receives a byte-pointer to memory, it can only -;; draw byte-sized and byte-aligned sprites. This means that the box cannot -;; start on non-byte aligned pixels (like odd-pixels, for instance) and -;; their sizes must be a multiple of a byte (2 in mode 0, 4 in mode 1 and -;; 8 in mode 2). -;; * This function *will not work from ROM*, as it uses self-modifying code. -;; * This function requires the CPC firmware to be DISABLED. Otherwise, random crashes might happen due to side effects. -;; -;; Destroyed Register values: -;; AF, BC, DE, HL, BC', DE', HL', IX -;; -;; Required memory: -;; C-bindings - 118 bytes -;; ASM-bindings - 108 bytes -;; -;; Time Measures: -;; (start code) -;; Case | microSecs (us) | CPU Cycles -;; ---------------------------------------------------------------- -;; | 29 + (62 + 23W)H | 116 + (248 + 92W)H -;; ---------------------------------------------------------------- -;; W=2,H=16 | 1757 | 7028 -;; W=4,H=32 | 4957 | 19828 -;; ---------------------------------------------------------------- -;; Asm saving | -16 | -64 -;; ---------------------------------------------------------------- -;; (end code) -;; W = *width* in bytes, H = *height* in bytes, HH = [(H-1)/8] -;; -;; Credits: -;; Original routine optimized by @Docent and discussed in CPCWiki : -;; http://www.cpcwiki.eu/forum/programming/cpctelera-colorize-sprite/ -;; -;; Thanks to all of them for their help and support. -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -.globl dc_mode0_ct - -;; Macro to convert Pixel to xAxC xBxD format -.macro convertPixel - ;; From cpct_px2byteM0 - ld bc, #dc_mode0_ct ;; [3] BC points to conversion table (dc_mode0_ct) - - ;; Compute BC += A - add c ;; [1] | C += A - ld c, a ;; [1] | - sub a ;; [1] A = 0 (preserving Carry Flag) - adc b ;; [1] | B += Carry - ld b, a ;; [1] | - - ;; A = *(BC + A) - ld a, (bc) ;; [2] A = Value stored at the table pointed by BC -.endm - - ;; Convert newColor to pixel format (E) - ld a, h ;; [1] A = H new color index - convertPixel ;; [10] | Convert into A - ld e, a ;; [1] | E = A new color : xAxC xBxD - - ;; Convert oldColor to pixel format (D) - ld a, l ;; [1] A = L old color index - convertPixel ;; [10] | Convert into A - ld d, a ;; [1] | D = A old color : xAxC xBxD - - ld c, #0x55 ;; [2] C = Mask to get pixel A : xAxC xBxD - - exx ;; [1] Switch to Alternate registers - - ld__ixl_c ;; [1] IXL = C (Width) - ld c, b ;; [1] C = B (Height) - -convertLoop: - ld (startLine), de ;; [6] Store DE start line (DestMem) - ld__b_ixl ;; [2] B = IXL (Sprite Width) - -lineLoop: - ld a, (hl) ;; [2] A = (HL) current Byte of sprite - exx ;; [1] Switch to Default registers - - ld l, a ;; [1] L = A current Byte of sprite : ABAB ABAB - and c ;; [2] A |= C (C = 0x55) : xBxB xBxB - - cp d ;; [1] Test if pixel (A) is the old colour to be replaced (D) - jr nz, readPixelA ;; [2/3] If not equal go to next pixel - ld a, e ;; [1] else A = new colour to set (E) - -;; Pixel Mode 0 = ABAB ABAB -readPixelA: - ld h, a ;; [1] H = A (current colorized sprite) : xBxB xBxB - ld a, l ;; [1] L = A current Byte of sprite : ABAB ABAB - rrca ;; [1] A (current byte of sprite) >> 1 : ABAB ABAB -> xABA BABA - and c ;; [2] A |= Mask (0x55) : xAxA xAxA - - cp d ;; [1] Test if pixel (A) is the old colour to be replaced (D) - jr nz, readPixelB ;; [2/3] If not equal go to next pixel - ld a, e ;; [1] else A = new colour to set (E) - -readPixelB: - rlca ;; [1] A = xAxA xAxA << 1 : AxAx AxAx - or h ;; [1] A |= H (xBxB xBxB) : ABAB ABAB - - exx ;; [1] Switch to Alternate registers - -drawByte: - ld (de), a ;; [2] Update current sprite byte with pixels - inc hl ;; [2] Next byte sprite source - inc de ;; [2] Next byte sprite colorized - djnz lineLoop ;; [3] Decrement B (Width) if B != 0 goto lineLoop - - dec c ;; [1] Decrement C (Height) - jr z, end ;; [2/3] If C == O goto end - -startLine = .+1 ;; Placeholder for the Start line adress - ld de, #0000 ;; [3] DE = Start Line - - ld a, d ;; [1] Start of next pixel line normally is 0x0800 bytes away. - add #0x08 ;; [2] so we add it to DE (just by adding 0x08 to D) - ld d, a ;; [1] - and #0x38 ;; [2] We check if we have crossed memory boundary (every 8 pixel lines).. - - jr nz, convertLoop ;; [2/3] .. by checking the 4 bits that identify present memory line. - ;; .... If 0, we have crossed boundaries - -dms_sprite_8bit_boundary_crossed: - ld a, e ;; [1] DE = DE + 0xC050h - add #0x50 ;; [2] -- Relocate DE pointer to the start of the next pixel line: - ld e, a ;; [1] -- DE is moved forward 3 memory banks plus 50 bytes (4000h * 3) - ld a, d ;; [1] -- which effectively is the same as moving it 1 bank backwards and then - adc #0xC0 ;; [2] -- 50 bytes forwards (which is what we want to move it to the next pixel line) - ld d, a ;; [1] -- Calculations are made with 8 bit maths as it is faster than other alternatives here - - jr convertLoop ;; [3] Jump to continue with next pixel line - -end: - ;; Return is included in bindings - - diff --git a/examples/medium/colorReplace/src/asm/sprites/colorReplace/M0/cpct_drawSpriteColorizeM0_asmbindings.s b/examples/medium/colorReplace/src/asm/sprites/colorReplace/M0/cpct_drawSpriteColorizeM0_asmbindings.s deleted file mode 100644 index d5930a9aa..000000000 --- a/examples/medium/colorReplace/src/asm/sprites/colorReplace/M0/cpct_drawSpriteColorizeM0_asmbindings.s +++ /dev/null @@ -1,36 +0,0 @@ -;;-----------------------------LICENSE NOTICE------------------------------------ -;; This file is part of CPCtelera: An Amstrad CPC Game Engine -;; Copyright (C) 2017 Arnaud Bouche (Arnaud6128) -;; Copyright (C) 2017 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) -;; -;; This program is free software: you can redistribute it and/or modify -;; it under the terms of the GNU Lesser General Public License as published by -;; the Free Software Foundation, either version 3 of the License, or -;; (at your option) any later version. -;; -;; This program is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU Lesser General Public License for more details. -;; -;; You should have received a copy of the GNU Lesser General Public License -;; along with this program. If not, see <http://www.gnu.org/licenses/>. -;;------------------------------------------------------------------------------- -.module cpct_sprites - -.include "../../../macros/cpct_undocumentedOpcodes.s" - -;; -;; ASM bindings for <cpct_drawSpriteColorizeM0> -;; -cpct_drawSpriteColorizeM0_asm:: ;; Assembly entry point - - ;; GET Parameters from the stack - ld (dms_restore_ix + 2), ix ;; [6] Save IX to restore it before returning - pop hl ;; [3] HL = Return Address - -;;.include /cpct_drawSpriteColorizeM0.asm/ - -dms_restore_ix: - ld ix, #0000 ;; [4] Restore IX before returning - ret ;; [3] Return to caller \ No newline at end of file diff --git a/examples/medium/colorReplace/src/asm/sprites/colorReplace/M0/cpct_drawSpriteColorizeM0_cbindings.s b/examples/medium/colorReplace/src/asm/sprites/colorReplace/M0/cpct_drawSpriteColorizeM0_cbindings.s deleted file mode 100644 index ac5d57084..000000000 --- a/examples/medium/colorReplace/src/asm/sprites/colorReplace/M0/cpct_drawSpriteColorizeM0_cbindings.s +++ /dev/null @@ -1,48 +0,0 @@ -;;-----------------------------LICENSE NOTICE------------------------------------ -;; This file is part of CPCtelera: An Amstrad CPC Game Engine -;; Copyright (C) 2017 Arnaud Bouche (Arnaud6128) -;; Copyright (C) 2017 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) -;; -;; This program is free software: you can redistribute it and/or modify -;; it under the terms of the GNU Lesser General Public License as published by -;; the Free Software Foundation, either version 3 of the License, or -;; (at your option) any later version. -;; -;; This program is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU Lesser General Public License for more details. -;; -;; You should have received a copy of the GNU Lesser General Public License -;; along with this program. If not, see <http://www.gnu.org/licenses/>. -;;------------------------------------------------------------------------------- -.module cpct_sprites - -.include "../../../macros/cpct_undocumentedOpcodes.s" - -;; -;; C bindings for <cpct_drawSpriteColorizeM0> -;; -;; 33 us, 10 bytes -;; -_cpct_drawSpriteColorizeM0:: - - ;; GET Parameters from the stack - ld (dms_restore_ix + 2), ix ;; [6] Save IX to restore it before returning - pop hl ;; [3] HL = Return Address - - exx - pop hl ;; [3] HL' = Source address (Sprite) - pop de ;; [3] DE' = Destination Memory - pop bc ;; [5] BC' = (B = Sprite Height, C = Width) - exx - - ex (sp), hl ;; [6] HL = (H = newColor, L = oldColor) - ;; ... and leave Return Address at (SP) as we don't need to restore - ;; ... stack status because callin convention is __z88dk_callee - -.include /cpct_drawSpriteColorizeM0.asm/ - -dms_restore_ix: - ld ix, #0000 ;; [4] Restore IX before returning - ret ;; [3] Return to caller \ No newline at end of file diff --git a/examples/medium/colorReplace/src/asm/sprites/colorReplace/M0/cpct_drawSpriteMaskedAlignedColorizeM0.asm b/examples/medium/colorReplace/src/asm/sprites/colorReplace/M0/cpct_drawSpriteMaskedAlignedColorizeM0.asm deleted file mode 100644 index 93b252423..000000000 --- a/examples/medium/colorReplace/src/asm/sprites/colorReplace/M0/cpct_drawSpriteMaskedAlignedColorizeM0.asm +++ /dev/null @@ -1,215 +0,0 @@ -;;-----------------------------LICENSE NOTICE------------------------------------ -;; This file is part of CPCtelera: An Amstrad CPC Game Engine -;; Copyright (C) 2017 Arnaud Bouche (Arnaud6128) -;; Copyright (C) 2017 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) -;; -;; This program is free software: you can redistribute it and/or modify -;; it under the terms of the GNU Lesser General Public License as published by -;; the Free Software Foundation, either version 3 of the License, or -;; (at your option) any later version. -;; -;; This program is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU Lesser General Public License for more details. -;; -;; You should have received a copy of the GNU Lesser General Public License -;; along with this program. If not, see <http://www.gnu.org/licenses/>. -;;------------------------------------------------------------------------------- -.module cpct_sprites - -.globl dc_mode0_ct - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; -;; Function: cpct_drawSpriteMaskedAlignedColorizeM0 -;; -;; Directly replace a color and draw a sprite Masked Aligned to video memory. -;; -;; C Definition: -;; void <cpct_drawSpriteMaskedAlignedColorizeM0> (void* *sprite*, void* *memory*, <u8> *width*, <u8> *height*, -;; <u8> *oldColor*, <u8> *newColor*, <u8*> *pmasktable*) __z88dk_callee; -;; -;; Input Parameters (10 bytes): -;; (2B HL') sprite - Source Sprite Pointer (array of pixel data) -;; (2B DE') memory - Destination video memory pointer -;; (1B C' ) height - Sprite Height in bytes (>0) -;; (1B B' ) width - Sprite Width in *bytes* (Beware, *not* in pixels!) -;; (1B E ) oldColor - Color to replace -;; (1B D ) newColor - New color -;; (2B HL) pmasktable - Pointer to the aligned mask table used to create transparency -;; -;; Assembly call (Input parameters on registers): -;; > call cpct_drawSpriteMaskedAlignedColorizeM0_asm -;; -;; Parameter Restrictions: -;; * *sprite* must be an array containing sprite's pixels data in screen pixel format -;; Sprite must be rectangular and all bytes in the array must be consecutive pixels, -;; starting from top-left corner and going left-to-right, top-to-bottom down to the -;; bottom-right corner. Total amount of bytes in pixel array should be *width* x *height*. -;; * *memory* could be any place in memory, inside or outside current video memory. It -;; will be equally treated as video memory (taking into account CPC's video memory -;; disposition). This lets you copy sprites to software or hardware backbuffers, and -;; not only video memory. -;; * *width* must be the width of the sprite *in bytes*. Always remember that the width must be -;; expressed in bytes and *not* in pixels. -;; The correspondence is mode 0 : 1 byte = 2 pixels -;; * *height* must be the height of the sprite in bytes, and must be greater than 0. -;; There is no practical upper limit to this value. Height of a sprite in -;; bytes and pixels is the same value, as bytes only group consecutive pixels in -;; the horizontal space. -;; * *oldColor* must be the index of color (0 to 15) to replace -;; * *newColor* must be the index of the new color (0 to 15) -;; -;; Known limitations: -;; * This function does not do any kind of boundary check or clipping. If you -;; try to draw sprites on the frontier of your video memory or screen buffer -;; if might potentially overwrite memory locations beyond boundaries. This -;; could cause your program to behave erratically, hang or crash. Always -;; take the necessary steps to guarantee that you are drawing inside screen -;; or buffer boundaries. -;; * As this function receives a byte-pointer to memory, it can only -;; draw byte-sized and byte-aligned sprites. This means that the box cannot -;; start on non-byte aligned pixels (like odd-pixels, for instance) and -;; their sizes must be a multiple of a byte (2 in mode 0, 4 in mode 1 and -;; 8 in mode 2). -;; * This function *will not work from ROM*, as it uses self-modifying code. -;; * This function requires the CPC firmware to be DISABLED. Otherwise, random crashes might happen due to side effects. -;; -;; Destroyed Register values: -;; AF, BC, DE, HL, BC', DE', HL', IX -;; -;; Required memory: -;; C-bindings - 112 bytes -;; ASM-bindings - 96 bytes -;; -;; Time Measures: -;; (start code) -;; Case | microSecs (us) | CPU Cycles -;; ---------------------------------------------------------------- -;; | 32 + (58 + 20W)H | 128 + (232 + 80W)H -;; ---------------------------------------------------------------- -;; W=2,H=16 | 1600 | 6400 -;; W=4,H=32 | 4448 | 17792 -;; ---------------------------------------------------------------- -;; Asm saving | -16 | -64 -;; ---------------------------------------------------------------- -;; (end code) -;; W = *width* in bytes, H = *height* in bytes, HH = [(H-1)/8] -;; -;; Credits: -;; Original routine optimized by @Docent and discussed in CPCWiki : -;; http://www.cpcwiki.eu/forum/programming/cpctelera-colorize-sprite/ -;; -;; Thanks to all of them for their help and support. -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -;; Macro to convert Pixel to xAxC xBxD format -.macro convertPixel - ;; From cpct_px2byteM0 - ld bc, #dc_mode0_ct ;; [3] BC points to conversion table (dc_mode0_ct) - - ;; Compute BC += A - add c ;; [1] | C += A - ld c, a ;; [1] | - sub a ;; [1] A = 0 (preserving Carry Flag) - adc b ;; [1] | B += Carry - ld b, a ;; [1] | - - ;; A = *(BC + A) - ld a, (bc) ;; [2] A = Value stored at the table pointed by BC -.endm - - ;; Convert newColor to pixel format (E) - ld a, h ;; [1] A = H new color index - convertPixel ;; [10] | Convert into A - ld e, a ;; [1] | E = A new color : xAxC xBxD - - ;; Convert oldColor to pixel format (D) - ld a, l ;; [1] A = L old color index - convertPixel ;; [10] | Convert into A - ld b, d - ld d, a ;; [1] | D = A old color : xAxC xBxD - - ld c, #0x55 ;; [2] C = Mask to get pixel A : xAxC xBxD - exx ;; [1] Switch to Alternate registers - - ld__ixl_c ;; [1] IXL = C (Width) - ld c, b ;; [1] C = B (Height) - -convertLoop: - push de ;; [4] Store DE start line (DestMem) - ld__b_ixl ;; [2] B = IXL (Sprite Width) - -lineLoop: - ld a, (hl) ;; [2] A = (HL) current Byte of sprite - exx ;; [1] Switch to Default registers - - ld l, a ;; [1] L = A current Byte of sprite : ABAB ABAB - and c ;; [2] A |= C (C = 0x55) : xBxB xBxB - - cp d ;; [1] Test if pixel (A) is the old colour to be replaced (D) - jr nz, readPixelA ;; [2/3] If not equal go to next pixel - ld a, e ;; [1] else A = new colour to set (E) - -;; Pixel Mode 0 = ABAB ABAB -readPixelA: - ld h, a ;; [1] H = A (current colorized sprite) : xBxB xBxB - ld a, l ;; [1] L = A current Byte of sprite : ABAB ABAB - rrca ;; [1] A (current byte of sprite) >> 1 : ABAB ABAB -> xABA BABA - and c ;; [2] A |= Mask (0x55) : xAxA xAxA - - cp d ;; [1] Test if pixel (A) is the old colour to be replaced (D) - jr nz, readPixelB ;; [2/3] If not equal go to next pixel - ld a, e ;; [1] else A = new colour to set (E) - -readPixelB: - rlca ;; [1] A = xAxA xAxA << 1 : AxAx AxAx - or h ;; [1] A |= H (xBxB xBxB) : ABAB ABAB - -drawByte: - ld h, b ;; [1] H = B (Masked table adress High Byte) - ld l, a ;; [1] Access mask table element (table must be 256-byte aligned) - exx ;; [1] Switch to Alternate registers - - ld a, (de) ;; [2] Get the value of the byte of the screen where we are going to draw - exx ;; [1] Switch to Default registers - - and (hl) ;; [2] Erase background part that is to be overwritten (Mask step 1) - or l ;; [1] Add up background and sprite information in one byte (Mask step 2) - exx ;; [1] Switch to Alternate registers - - ld (de), a ;; [2] Save modified background + sprite data information into memory - - inc hl ;; [2] Next byte sprite source - inc de ;; [2] Next byte sprite colorized - djnz lineLoop ;; [3] Decrement B (Width) if B != 0 goto lineLoop - - dec c ;; [1] Decrement C (Height) - jr z, end ;; [2/3] If C == O goto end - - pop de ;; [3] Restore DE start line (DestMem) - - ld a, d ;; [1] Start of next pixel line normally is 0x0800 bytes away. - add #0x08 ;; [2] so we add it to DE (just by adding 0x08 to D) - ld d, a ;; [1] - and #0x38 ;; [2] We check if we have crossed memory boundary (every 8 pixel lines).. - - jr nz, convertLoop ;; [2/3] .. by checking the 4 bits that identify present memory line. - ;; .... If 0, we have crossed boundaries - -dms_sprite_8bit_boundary_crossed: - ld a, e ;; [1] DE = DE + 0xC050h - add #0x50 ;; [2] -- Relocate DE pointer to the start of the next pixel line: - ld e, a ;; [1] -- DE is moved forward 3 memory banks plus 50 bytes (4000h * 3) - ld a, d ;; [1] -- which effectively is the same as moving it 1 bank backwards and then - adc #0xC0 ;; [2] -- 50 bytes forwards (which is what we want to move it to the next pixel line) - ld d, a ;; [1] -- Calculations are made with 8 bit maths as it is faster than other alternatives here - - jr convertLoop ;; [3] Jump to continue with next pixel line - -end: - pop de ;; [3] Empty stack by getting last element (DestMem) - ;; Return is included in bindings - - diff --git a/examples/medium/colorReplace/src/asm/sprites/colorReplace/M0/cpct_drawSpriteMaskedAlignedColorizeM0_asmbindings.s b/examples/medium/colorReplace/src/asm/sprites/colorReplace/M0/cpct_drawSpriteMaskedAlignedColorizeM0_asmbindings.s deleted file mode 100644 index 7828b8736..000000000 --- a/examples/medium/colorReplace/src/asm/sprites/colorReplace/M0/cpct_drawSpriteMaskedAlignedColorizeM0_asmbindings.s +++ /dev/null @@ -1,36 +0,0 @@ -;;-----------------------------LICENSE NOTICE------------------------------------ -;; This file is part of CPCtelera: An Amstrad CPC Game Engine -;; Copyright (C) 2017 Arnaud Bouche (Arnaud6128) -;; Copyright (C) 2017 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) -;; -;; This program is free software: you can redistribute it and/or modify -;; it under the terms of the GNU Lesser General Public License as published by -;; the Free Software Foundation, either version 3 of the License, or -;; (at your option) any later version. -;; -;; This program is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU Lesser General Public License for more details. -;; -;; You should have received a copy of the GNU Lesser General Public License -;; along with this program. If not, see <http://www.gnu.org/licenses/>. -;;------------------------------------------------------------------------------- -.module cpct_sprites - -.include "../../../macros/cpct_undocumentedOpcodes.s" - -;; -;; ASM bindings for <cpct_drawSpriteMaskedAlignedColorizeM0> -;; -cpct_drawSpriteMaskedAlignedColorizeM0_asm:: ;; Assembly entry point - - ;; GET Parameters from the stack - ld (dms_restore_ix + 2), ix ;; [6] Save IX to restore it before returning - pop hl ;; [3] HL = Return Address - -.include /cpct_drawSpriteMaskedAlignedColorizeM0.asm/ - -dms_restore_ix: - ld ix, #0000 ;; [4] Restore IX before returning - ret ;; [3] Return to caller \ No newline at end of file diff --git a/examples/medium/colorReplace/src/asm/sprites/colorReplace/M0/cpct_drawSpriteMaskedAlignedColorizeM0_cbindings.s b/examples/medium/colorReplace/src/asm/sprites/colorReplace/M0/cpct_drawSpriteMaskedAlignedColorizeM0_cbindings.s deleted file mode 100644 index 001ae99c3..000000000 --- a/examples/medium/colorReplace/src/asm/sprites/colorReplace/M0/cpct_drawSpriteMaskedAlignedColorizeM0_cbindings.s +++ /dev/null @@ -1,52 +0,0 @@ -;;-----------------------------LICENSE NOTICE------------------------------------ -;; This file is part of CPCtelera: An Amstrad CPC Game Engine -;; Copyright (C) 2017 Arnaud Bouche (Arnaud6128) -;; Copyright (C) 2017 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) -;; -;; This program is free software: you can redistribute it and/or modify -;; it under the terms of the GNU Lesser General Public License as published by -;; the Free Software Foundation, either version 3 of the License, or -;; (at your option) any later version. -;; -;; This program is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU Lesser General Public License for more details. -;; -;; You should have received a copy of the GNU Lesser General Public License -;; along with this program. If not, see <http://www.gnu.org/licenses/>. -;;------------------------------------------------------------------------------- -.module cpct_sprites - -.include "../../../macros/cpct_undocumentedOpcodes.s" - -;; -;; C bindings for <cpct_drawSpriteMaskedAlignedColorizeM0> -;; -;; 39 us, 16 bytes -;; -_cpct_drawSpriteMaskedAlignedColorizeM0:: - - ;; GET Parameters from the stack - ld (dms_restore_ix + 2), ix ;; [6] Save IX to restore it before returning - pop hl ;; [3] HL = Return Address - - exx ;; [1] Switch to Alternate registers - pop hl ;; [3] HL' = Source address (Sprite) - pop de ;; [3] DE' = Destination Memory - pop bc ;; [5] BC' = (B = Sprite Height, C = Width) - - exx ;; [1] Switch to Default registers - pop de ;; [3] DE = (D = newColor, E = oldColor) - - ex (sp), hl ;; [6] HL = Table Mask address - ;; ... and leave Return Address at (SP) as we don't need to restore - ;; ... stack status because callin convention is __z88dk_callee - - ex de, hl ;; [1] HL <-> DE - -.include /cpct_drawSpriteMaskedAlignedColorizeM0.asm/ - -dms_restore_ix: - ld ix, #0000 ;; [4] Restore IX before returning - ret ;; [3] Return to caller \ No newline at end of file diff --git a/examples/medium/colorReplace/src/asm/sprites/colorReplace/M0/cpct_drawSpriteMaskedColorizeM0.asm b/examples/medium/colorReplace/src/asm/sprites/colorReplace/M0/cpct_drawSpriteMaskedColorizeM0.asm deleted file mode 100644 index e954fb3dc..000000000 --- a/examples/medium/colorReplace/src/asm/sprites/colorReplace/M0/cpct_drawSpriteMaskedColorizeM0.asm +++ /dev/null @@ -1,216 +0,0 @@ -;;-----------------------------LICENSE NOTICE------------------------------------ -;; This file is part of CPCtelera: An Amstrad CPC Game Engine -;; Copyright (C) 2017 Arnaud Bouche -;; Copyright (C) 2017 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) -;; -;; This program is free software: you can redistribute it and/or modify -;; it under the terms of the GNU Lesser General Public License as published by -;; the Free Software Foundation, either version 3 of the License, or -;; (at your option) any later version. -;; -;; This program is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU Lesser General Public License for more details. -;; -;; You should have received a copy of the GNU Lesser General Public License -;; along with this program. If not, see <http://www.gnu.org/licenses/>. -;;------------------------------------------------------------------------------- -.module cpct_sprites - -.globl dc_mode0_ct - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; -;; Function: cpct_drawSpriteMaskedColorizeM0 -;; -;; Directly replace a color and draw a sprite Masked to video memory. -;; -;; C Definition: -;; void <cpct_drawSpriteMaskedColorizeM0> (void* *sprite*, void* *memory*, <u8> *width*, <u8> *height*, <u8> *oldColor*, <u8> *newColor*) __z88dk_callee; -;; -;; Input Parameters (8 bytes): -;; (2B HL') sprite - Source Sprite Pointer (array of pixel data) -;; (2B DE') memory - Destination video memory pointer -;; (1B C' ) height - Sprite Height in bytes (>0) -;; (1B B' ) width - Sprite Width in *bytes* (Beware, *not* in pixels!) -;; (1B L ) oldColor - Color to replace -;; (1B H ) newColor - New color -;; -;; Assembly call (Input parameters on registers): -;; > call cpct_drawSpriteMaskedColorizeM0_asm -;; -;; Parameter Restrictions: -;; * *sprite* must be an array containing sprite's pixels data in screen pixel format -;; along with mask data. Each mask byte will contain enabled bits as those that should -;; be picked from the background (transparent) and disabled bits for those that will -;; be printed from sprite colour data. Each mask data byte must precede its associated -;; colour data byte. -;; Sprite must be rectangular and all bytes in the array must be consecutive pixels, -;; starting from top-left corner and going left-to-right, top-to-bottom down to the -;; bottom-right corner. Total amount of bytes in pixel array should be -;; 2 x *width* x *height* (mask data doubles array size). -;; * *memory* could be any place in memory, inside or outside current video memory. It -;; will be equally treated as video memory (taking into account CPC's video memory -;; disposition). This lets you copy sprites to software or hardware backbuffers, and -;; not only video memory. -;; * *width* must be the width of the sprite *in bytes*. Always remember that the width must be -;; expressed in bytes and *not* in pixels. -;; The correspondence is mode 0 : 1 byte = 2 pixels -;; * *height* must be the height of the sprite in bytes, and must be greater than 0. -;; There is no practical upper limit to this value. Height of a sprite in -;; bytes and pixels is the same value, as bytes only group consecutive pixels in -;; the horizontal space. -;; * *oldColor* must be the index of color (0 to 15) to replace -;; * *newColor* must be the index of the new color (0 to 15) -;; -;; Known limitations: -;; * This function does not do any kind of boundary check or clipping. If you -;; try to draw sprites on the frontier of your video memory or screen buffer -;; if might potentially overwrite memory locations beyond boundaries. This -;; could cause your program to behave erratically, hang or crash. Always -;; take the necessary steps to guarantee that you are drawing inside screen -;; or buffer boundaries. -;; * As this function receives a byte-pointer to memory, it can only -;; draw byte-sized and byte-aligned sprites. This means that the box cannot -;; start on non-byte aligned pixels (like odd-pixels, for instance) and -;; their sizes must be a multiple of a byte (2 in mode 0, 4 in mode 1 and -;; 8 in mode 2). -;; * This function *will not work from ROM*, as it uses self-modifying code. -;; * This function requires the CPC firmware to be DISABLED. Otherwise, random crashes might happen due to side effects. -;; -;; Destroyed Register values: -;; AF, BC, DE, HL, BC', DE', HL', IX -;; -;; Required memory: -;; C-bindings - 115 bytes -;; ASM-bindings - 102 bytes -;; -;; Time Measures: -;; (start code) -;; Case | microSecs (us) | CPU Cycles -;; ---------------------------------------------------------------- -;; Best | 29 + (50 + 36W)H | 116 + (200 + 144W)H -;; ---------------------------------------------------------------- -;; W=2,H=16 | 1981 | 7924 -;; W=4,H=32 | 6237 | 24948 -;; ---------------------------------------------------------------- -;; Asm saving | -16 | -64 -;; ---------------------------------------------------------------- -;; (end code) -;; W = *width* in bytes, H = *height* in bytes, HH = [(H-1)/8] -;; -;; Credits: -;; Original routine optimized by @Docent and discussed in CPCWiki : -;; http://www.cpcwiki.eu/forum/programming/cpctelera-colorize-sprite/ -;; -;; Thanks to all of them for their help and support. -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -;; Macro to convert Pixel to xAxC xBxD format -.macro convertPixel - ;; From cpct_px2byteM0 - ld bc, #dc_mode0_ct ;; [3] BC points to conversion table (dc_mode0_ct) - - ;; Compute BC += A - add c ;; [1] | C += A - ld c, a ;; [1] | - sub a ;; [1] A = 0 (preserving Carry Flag) - adc b ;; [1] | B += Carry - ld b, a ;; [1] | - - ;; A = *(BC + A) - ld a, (bc) ;; [2] A = Value stored at the table pointed by BC -.endm - - ;; Convert newColor to pixel format (E) - ld a, h ;; [1] A = H new color index - convertPixel ;; [10] | Convert into A - ld e, a ;; [1] | E = A new color : xAxC xBxD - - ;; Convert oldColor to pixel format (D) - ld a, l ;; [1] A = L old color index - convertPixel ;; [10] | Convert into A - ld d, a ;; [1] | D = A old color : xAxC xBxD - - ld c, #0x55 ;; [2] C = Mask to get pixel A : xAxC xBxD - - exx ;; [1] Switch to Alternate registers - - ld__ixl_c ;; [1] IXL = C (Width) - ld c, b ;; [1] C = B (Height) - -convertLoop: - ld (startLine), de ;; [6] Store DE start line (DestMem) - ld__b_ixl ;; [2] B = IXL (Sprite Width) - -lineLoop: - inc hl ;; [2] Next byte sprite Color source - ld a, (hl) ;; [2] A = (HL) current Byte of sprite Color - dec hl ;; [2] Previous byte sprite Mask source - - exx ;; [1] Switch to Default registers - - ld l, a ;; [1] L = A current Byte of sprite : ABAB ABAB - and c ;; [2] A |= C (C = 0x55) : xBxB xBxB - - cp d ;; [1] Test if pixel (A) is the old colour to be replaced (D) - jr nz, readPixelA ;; [2/3] If not equal go to next pixel - ld a, e ;; [1] else A = new colour to set (E) - -;; Pixel Mode 0 = ABAB ABAB -readPixelA: - ld h, a ;; [1] H = A (current colorized sprite) : xBxB xBxB - ld a, l ;; [1] L = A current Byte of sprite : ABAB ABAB - rrca ;; [1] A (current byte of sprite) >> 1 : ABAB ABAB -> xABA BABA - and c ;; [2] A |= Mask (0x55) : xAxA xAxA - - cp d ;; [1] Test if pixel (A) is the old colour to be replaced (D) - jr nz, readPixelB ;; [2/3] If not equal go to next pixel - ld a, e ;; [1] else A = new colour to set (E) - -readPixelB: - rlca ;; [1] A = xAxA xAxA << 1 : AxAx AxAx - or h ;; [1] A |= H (xBxB xBxB) : ABAB ABAB - -drawByte: - exx ;; [1] Switch to Alternate registers - ld (sprite_color), a ;; [4] sprite_color = A (Sprite Byte) - - ld a, (de) ;; [2] Get next background byte into A - and (hl) ;; [2] Erase background part that is to be overwritten (Mask step 1) - inc hl ;; [3] HL += 1 => Point HL to Sprite Colour information -sprite_color = .+1 ;; Placeholder for the Sprite Color computed - or #00 ;; [2] Add up background and sprite information in one byte (Mask step 2) - ld (de), a ;; [2] Save modified background + sprite data information into memory - - inc hl ;; [2] Next byte sprite source - inc de ;; [2] Next byte Dest Memory - djnz lineLoop ;; [3] Decrement B (Width) if B != 0 goto lineLoop - - dec c ;; [1] Decrement C (Height) - jr z, end ;; [2/3] If C == O goto end - -startLine = .+1 ;; Placeholder for the Start line adress - ld de, #0000 ;; [3] DE = Start Line - - ld a, d ;; [1] Start of next pixel line normally is 0x0800 bytes away. - add #0x08 ;; [2] so we add it to DE (just by adding 0x08 to D) - ld d, a ;; [1] - and #0x38 ;; [2] We check if we have crossed memory boundary (every 8 pixel lines).. - - jr nz, convertLoop ;; [2/3] .. by checking the 4 bits that identify present memory line. - ;; .... If 0, we have crossed boundaries - -dms_sprite_8bit_boundary_crossed: - ld a, e ;; [1] DE = DE + 0xC050h - add #0x50 ;; [2] -- Relocate DE pointer to the start of the next pixel line: - ld e, a ;; [1] -- DE is moved forward 3 memory banks plus 50 bytes (4000h * 3) - ld a, d ;; [1] -- which effectively is the same as moving it 1 bank backwards and then - adc #0xC0 ;; [2] -- 50 bytes forwards (which is what we want to move it to the next pixel line) - ld d, a ;; [1] -- Calculations are made with 8 bit maths as it is faster than other alternatives here - - jr convertLoop ;; [3] Jump to continue with next pixel line - -end: - ;; Return is included in bindings \ No newline at end of file diff --git a/examples/medium/colorReplace/src/asm/sprites/colorReplace/M0/cpct_drawSpriteMaskedColorizeM0_asmbindings.s b/examples/medium/colorReplace/src/asm/sprites/colorReplace/M0/cpct_drawSpriteMaskedColorizeM0_asmbindings.s deleted file mode 100644 index 1a40a3186..000000000 --- a/examples/medium/colorReplace/src/asm/sprites/colorReplace/M0/cpct_drawSpriteMaskedColorizeM0_asmbindings.s +++ /dev/null @@ -1,36 +0,0 @@ -;;-----------------------------LICENSE NOTICE------------------------------------ -;; This file is part of CPCtelera: An Amstrad CPC Game Engine -;; Copyright (C) 2017 Arnaud Bouche (Arnaud6128) -;; Copyright (C) 2017 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) -;; -;; This program is free software: you can redistribute it and/or modify -;; it under the terms of the GNU Lesser General Public License as published by -;; the Free Software Foundation, either version 3 of the License, or -;; (at your option) any later version. -;; -;; This program is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU Lesser General Public License for more details. -;; -;; You should have received a copy of the GNU Lesser General Public License -;; along with this program. If not, see <http://www.gnu.org/licenses/>. -;;------------------------------------------------------------------------------- -.module cpct_sprites - -.include "../../../macros/cpct_undocumentedOpcodes.s" - -;; -;; ASM bindings for <cpct_drawSpriteMaskedColorizeM0> -;; -cpct_drawSpriteMaskedColorizeM0_asm:: ;; Assembly entry point - - ;; GET Parameters from the stack - ld (dms_restore_ix + 2), ix ;; [6] Save IX to restore it before returning - pop hl ;; [3] HL = Return Address - -.include /cpct_drawSpriteMaskedColorizeM0.asm/ - -dms_restore_ix: - ld ix, #0000 ;; [4] Restore IX before returning - ret ;; [3] Return to caller \ No newline at end of file diff --git a/examples/medium/colorReplace/src/asm/sprites/colorReplace/M0/cpct_drawSpriteMaskedColorizeM0_cbindings.s b/examples/medium/colorReplace/src/asm/sprites/colorReplace/M0/cpct_drawSpriteMaskedColorizeM0_cbindings.s deleted file mode 100644 index c39a879a4..000000000 --- a/examples/medium/colorReplace/src/asm/sprites/colorReplace/M0/cpct_drawSpriteMaskedColorizeM0_cbindings.s +++ /dev/null @@ -1,48 +0,0 @@ -;;-----------------------------LICENSE NOTICE------------------------------------ -;; This file is part of CPCtelera: An Amstrad CPC Game Engine -;; Copyright (C) 2017 Arnaud Bouche (Arnaud6128) -;; Copyright (C) 2017 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) -;; -;; This program is free software: you can redistribute it and/or modify -;; it under the terms of the GNU Lesser General Public License as published by -;; the Free Software Foundation, either version 3 of the License, or -;; (at your option) any later version. -;; -;; This program is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU Lesser General Public License for more details. -;; -;; You should have received a copy of the GNU Lesser General Public License -;; along with this program. If not, see <http://www.gnu.org/licenses/>. -;;------------------------------------------------------------------------------- -.module cpct_sprites - -.include "../../../macros/cpct_undocumentedOpcodes.s" - -;; -;; C bindings for <cpct_drawSpriteMaskedColorizeM0> -;; -;; 33 us, 13 bytes -;; -_cpct_drawSpriteMaskedColorizeM0:: - - ;; GET Parameters from the stack - ld (dms_restore_ix + 2), ix ;; [6] Save IX to restore it before returning - pop hl ;; [3] HL = Return Address - - exx - pop hl ;; [3] HL' = Source address (Sprite) - pop de ;; [3] DE' = Destination Memory - pop bc ;; [5] BC' = (B = Sprite Height, C = Width) - exx - - ex (sp), hl ;; [6] HL = (H = newColor, L = oldColor) - ;; ... and leave Return Address at (SP) as we don't need to restore - ;; ... stack status because callin convention is __z88dk_callee - -.include /cpct_drawSpriteMaskedColorizeM0.asm/ - -dms_restore_ix: - ld ix, #0000 ;; [4] Restore IX before returning - ret ;; [3] Return to caller \ No newline at end of file diff --git a/examples/medium/colorReplace/src/asm/sprites/colorReplace/M0/cpct_spriteColorizeM0.asm b/examples/medium/colorReplace/src/asm/sprites/colorReplace/M0/cpct_spriteColorizeM0.asm deleted file mode 100644 index 790e0b6ae..000000000 --- a/examples/medium/colorReplace/src/asm/sprites/colorReplace/M0/cpct_spriteColorizeM0.asm +++ /dev/null @@ -1,166 +0,0 @@ -;;-----------------------------LICENSE NOTICE------------------------------------ -;; This file is part of CPCtelera: An Amstrad CPC Game Engine -;; Copyright (C) 2017 Arnaud Bouche -;; Copyright (C) 2017 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) -;; -;; This program is free software: you can redistribute it and/or modify -;; it under the terms of the GNU Lesser General Public License as published by -;; the Free Software Foundation, either version 3 of the License, or -;; (at your option) any later version. -;; -;; This program is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU Lesser General Public License for more details. -;; -;; You should have received a copy of the GNU Lesser General Public License -;; along with this program. If not, see <http://www.gnu.org/licenses/>. -;;------------------------------------------------------------------------------- -.module cpct_sprites - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; -;; Function: cpct_spriteColorizeM0 -;; -;; Replace a color in a sprite and copy to another or the same sprite. -;; -;; C Definition: -;; void <cpct_spriteColorizeM0> (void* *sprite*, void* *spriteColor*, <u8> *width*, <u8> *height*, <u8> *oldColor*, <u8> *newColor*) __z88dk_callee; -;; -;; Input Parameters (6 bytes): -;; (2B HL') sprite - Source Sprite Pointer (array of pixel data) -;; (2B DE') spriteColor - Destination Sprite Pointer (can be also the Source Sprite) (array of pixel data) -;; (1B C' ) height - Sprite Height in bytes (>0) -;; (1B B' ) width - Sprite Width in *bytes* (Beware, *not* in pixels!) -;; (1B L ) oldColor - Color to replace -;; (1B H ) newColor - New color -;; -;; Assembly call (Input parameters on registers): -;; > call cpct_spriteColorizeM0_asm -;; -;; Parameter Restrictions: -;; * *sprite* must be an array containing sprite's pixels data in screen pixel format. -;; Sprite must be rectangular and all bytes in the array must be consecutive pixels, -;; starting from top-left corner and going left-to-right, top-to-bottom down to the -;; bottom-right corner. Total amount of bytes in pixel array should be *width* x *height*. -;; * *spriteColor* must be an array containing the new sprite's pixels data with the new color. -;; * *width* must be the width of the sprite *in bytes*. Always remember that the width must be -;; expressed in bytes and *not* in pixels. -;; The correspondence is mode 0 : 1 byte = 2 pixels -;; * *height* must be the height of the sprite in bytes, and must be greater than 0. -;; There is no practical upper limit to this value. Height of a sprite in -;; bytes and pixels is the same value, as bytes only group consecutive pixels in -;; the horizontal space. -;; * *oldColor* must be the index of color (0 to 15) to replace -;; * *newColor* must be the index of the new color (0 to 15) -;; -;; Known limitations: -;; * This function *will not work from ROM*, as it uses self-modifying code. -;; * This function requires the CPC firmware to be DISABLED. Otherwise, random crashes might happen due to side effects. -;; -;; Destroyed Register values: -;; AF, BC, DE, HL, BC', DE', HL', IX -;; -;; Required memory: -;; C-bindings - 81 bytes -;; ASM-bindings - 67 bytes -;; -;; Time Measures: -;; (start code) -;; Case | microSecs (us) | CPU Cycles -;; ---------------------------------------------------------------- -;; | 29 + (6 + 33W)H | 116 + (24 + 132W)H -;; ---------------------------------------------------------------- -;; W=2,H=16 | 1181 | 4724 -;; W=4,H=32 | 4445 | 17780 -;; ---------------------------------------------------------------- -;; Asm saving | -16 | -64 -;; ---------------------------------------------------------------- -;; (end code) -;; W = *width* in bytes, H = *height* in bytes -;; -;; Credits: -;; Original routine optimized by @Docent and discussed in CPCWiki : -;; http://www.cpcwiki.eu/forum/programming/cpctelera-colorize-sprite/ -;; -;; Thanks to all of them for their help and support. -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -.globl dc_mode0_ct - -;; Macro to convert Pixel to xAxC xBxD format -.macro convertPixel - ;; From cpct_px2byteM0 - ld bc, #dc_mode0_ct ;; [3] BC points to conversion table (dc_mode0_ct) - - ;; Compute BC += A - add c ;; [1] | C += A - ld c, a ;; [1] | - sub a ;; [1] A = 0 (preserving Carry Flag) - adc b ;; [1] | B += Carry - ld b, a ;; [1] | - - ;; A = *(BC + A) - ld a, (bc) ;; [2] A = Value stored at the table pointed by BC -.endm - - ;; Convert newColor to pixel format (E) - ld a, h ;; [1] A = H new color index - convertPixel ;; [10] | Convert into A - ld e, a ;; [1] | E = A new color : xAxC xBxD - - ;; Convert oldColor to pixel format (D) - ld a, l ;; [1] A = L old color index - convertPixel ;; [10] | Convert into A - ld d, a ;; [1] | D = A old color : xAxC xBxD - - ld c, #0x55 ;; [2] C = Mask to get pixel A : xAxC xBxD - exx ;; [1] Switch to Alternate registers - - ld__ixl_c ;; [1] IXL = C (Width) - ld c, b ;; [1] C = B (Height) - -convertLoop: - ld__b_ixl ;; [2] B = IXL (Sprite Width) - -lineLoop: - ld a, (hl) ;; [2] A = (HL) current Byte of sprite - exx ;; [1] Switch to Default registers - - ld l, a ;; [1] L = A current Byte of sprite : ABAB ABAB - and c ;; [2] A |= C (C = 0x55) : xBxB xBxB - - cp d ;; [1] Test if pixel (A) is the old colour to be replaced (D) - jr nz, readPixelA ;; [2/3] If not equal go to next pixel - ld a, e ;; [1] else A = new colour to set (E) - -;; Pixel Mode 0 = ABAB ABAB -readPixelA: - ld h, a ;; [1] H = A (current colorized sprite) : xBxB xBxB - ld a, l ;; [1] L = A current Byte of sprite : ABAB ABAB - rrca ;; [1] A (current byte of sprite) >> 1 : ABAB ABAB -> xABA BABA - and c ;; [2] A |= Mask (0x55) : xAxA xAxA - - cp d ;; [1] Test if pixel (A) is the old colour to be replaced (D) - jr nz, readPixelB ;; [2/3] If not equal go to next pixel - ld a, e ;; [1] else A = new colour to set (E) - -readPixelB: - rlca ;; [1] A = xAxA xAxA << 1 : AxAx AxAx - or h ;; [1] A |= H (xBxB xBxB) : ABAB ABAB - -setByte: - exx ;; [1] Switch to Alternate registers - - ld (de), a ;; [2] Update current sprite byte with pixels - inc hl ;; [2] Next byte sprite source - inc de ;; [2] Next byte sprite colorized - djnz lineLoop ;; [3] Decrement B (Width) if != 0 goto lineLoop - -nextLine: - dec c ;; [1] Decrement C (Height) - jr nz, convertLoop ;; [2/3] If != O goto convertLoop - -end: - ;; Return is included in bindings - diff --git a/examples/medium/colorReplace/src/asm/sprites/colorReplace/M0/cpct_spriteColorizeM0_asmbindings.s b/examples/medium/colorReplace/src/asm/sprites/colorReplace/M0/cpct_spriteColorizeM0_asmbindings.s deleted file mode 100644 index 9ac97a5e6..000000000 --- a/examples/medium/colorReplace/src/asm/sprites/colorReplace/M0/cpct_spriteColorizeM0_asmbindings.s +++ /dev/null @@ -1,36 +0,0 @@ -;;-----------------------------LICENSE NOTICE------------------------------------ -;; This file is part of CPCtelera: An Amstrad CPC Game Engine -;; Copyright (C) 2017 Arnaud Bouche (Arnaud6128) -;; Copyright (C) 2017 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) -;; -;; This program is free software: you can redistribute it and/or modify -;; it under the terms of the GNU Lesser General Public License as published by -;; the Free Software Foundation, either version 3 of the License, or -;; (at your option) any later version. -;; -;; This program is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU Lesser General Public License for more details. -;; -;; You should have received a copy of the GNU Lesser General Public License -;; along with this program. If not, see <http://www.gnu.org/licenses/>. -;;------------------------------------------------------------------------------- -.module cpct_sprites - -.include "../../../macros/cpct_undocumentedOpcodes.s" - -;; -;; ASM bindings for <cpct_spriteColorizeM0> -;; -cpct_spriteColorizeM0_asm:: ;; Assembly entry point - - ;; GET Parameters from the stack - ld (dms_restore_ix + 2), ix ;; [6] Save IX to restore it before returning - pop hl ;; [3] HL = Return Address - -.include /cpct_spriteColorizeM0.asm/ - -dms_restore_ix: - ld ix, #0000 ;; [4] Restore IX before returning - ret ;; [3] Return to caller \ No newline at end of file diff --git a/examples/medium/colorReplace/src/asm/sprites/colorReplace/M0/cpct_spriteColorizeM0_cbindings.s b/examples/medium/colorReplace/src/asm/sprites/colorReplace/M0/cpct_spriteColorizeM0_cbindings.s deleted file mode 100644 index f31436707..000000000 --- a/examples/medium/colorReplace/src/asm/sprites/colorReplace/M0/cpct_spriteColorizeM0_cbindings.s +++ /dev/null @@ -1,48 +0,0 @@ -;;-----------------------------LICENSE NOTICE------------------------------------ -;; This file is part of CPCtelera: An Amstrad CPC Game Engine -;; Copyright (C) 2017 Arnaud Bouche -;; Copyright (C) 2017 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) -;; -;; This program is free software: you can redistribute it and/or modify -;; it under the terms of the GNU Lesser General Public License as published by -;; the Free Software Foundation, either version 3 of the License, or -;; (at your option) any later version. -;; -;; This program is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU Lesser General Public License for more details. -;; -;; You should have received a copy of the GNU Lesser General Public License -;; along with this program. If not, see <http://www.gnu.org/licenses/>. -;;------------------------------------------------------------------------------- -.module cpct_sprites - -.include "../../../macros/cpct_undocumentedOpcodes.s" - -;; -;; C bindings for <cpct_spriteColorizeM0> -;; -;; 33 us, 14 bytes -;; -_cpct_spriteColorizeM0:: - - ;; GET Parameters from the stack - ld (dms_restore_ix + 2), ix ;; [6] Save IX to restore it before returning - pop hl ;; [3] HL = Return Address - - exx - pop hl ;; [3] HL' = Source address (Sprite) - pop de ;; [3] DE' = Destination Sprite color - pop bc ;; [5] BC' = (B = Sprite Height, C = Width) - exx - - ex (sp), hl ;; [6] HL = (H = newColor, L = oldColor) - ;; ... and leave Return Address at (SP) as we don't need to restore - ;; ... stack status because callin convention is __z88dk_callee - -.include /cpct_spriteColorizeM0.asm/ - -dms_restore_ix: - ld ix, #0000 ;; [4] Restore IX before returning - ret ;; [3] Return to caller \ No newline at end of file diff --git a/examples/medium/colorReplace/src/asm/sprites/colorReplace/M0/cpct_spriteMaskedColorizeM0.asm b/examples/medium/colorReplace/src/asm/sprites/colorReplace/M0/cpct_spriteMaskedColorizeM0.asm deleted file mode 100644 index 1f6101790..000000000 --- a/examples/medium/colorReplace/src/asm/sprites/colorReplace/M0/cpct_spriteMaskedColorizeM0.asm +++ /dev/null @@ -1,175 +0,0 @@ -;;-----------------------------LICENSE NOTICE------------------------------------ -;; This file is part of CPCtelera: An Amstrad CPC Game Engine -;; Copyright (C) 2017 Arnaud Bouche (Arnaud6128) -;; Copyright (C) 2017 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) -;; -;; This program is free software: you can redistribute it and/or modify -;; it under the terms of the GNU Lesser General Public License as published by -;; the Free Software Foundation, either version 3 of the License, or -;; (at your option) any later version. -;; -;; This program is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU Lesser General Public License for more details. -;; -;; You should have received a copy of the GNU Lesser General Public License -;; along with this program. If not, see <http://www.gnu.org/licenses/>. -;;------------------------------------------------------------------------------- -.module cpct_sprites - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; -;; Function: cpct_spriteMaskedColorizeM0 -;; -;; Replace a color in a Masked sprite and copy to another or the same sprite. -;; -;; C Definition: -;; void <cpct_spriteMaskedColorizeM0> (void* *sprite*, void* *spriteColor*, <u8> *width*, <u8> *height*, <u8> *oldColor*, <u8> *newColor*) __z88dk_callee; -;; -;; Input Parameters (6 bytes): -;; (2B HL') sprite - Source Sprite Pointer (array of pixel data) -;; (2B DE') spriteColor - Destination Sprite Pointer (can be also the Source Sprite) (array of pixel data) -;; (1B C') height - Sprite Height in bytes (>0) -;; (1B B') width - Sprite Width in *bytes* (Beware, *not* in pixels!) -;; (1B L) oldColor - Color to replace -;; (1B H) newColor - New color -;; -;; Assembly call (Input parameters on registers): -;; > call cpct_spriteMaskedColorizeM0_asm -;; -;; Parameter Restrictions: -;; * *sprite* must be an array containing sprite's pixels data in screen pixel format -;; along with mask data. Each mask byte will contain enabled bits as those that should -;; be picked from the background (transparent) and disabled bits for those that will -;; be printed from sprite colour data. Each mask data byte must precede its associated -;; colour data byte. -;; Sprite must be rectangular and all bytes in the array must be consecutive pixels, -;; starting from top-left corner and going left-to-right, top-to-bottom down to the -;; bottom-right corner. Total amount of bytes in pixel array should be -;; 2 x *width* x *height* (mask data doubles array size). -;; * *spriteColor* must be an array containing the new sprite's pixels data with the new color. -;; Total amount of bytes in pixel array should be 2 x *width* x *height* (mask data doubles array size). -;; * *width* must be the width of the sprite *in bytes*. Always remember that the width must be -;; expressed in bytes and *not* in pixels. -;; The correspondence is mode 0 : 1 byte = 2 pixels -;; * *height* must be the height of the sprite in bytes, and must be greater than 0. -;; There is no practical upper limit to this value. Height of a sprite in -;; bytes and pixels is the same value, as bytes only group consecutive pixels in -;; the horizontal space. -;; * *oldColor* must be the index of color (0 to 15) to replace -;; * *newColor* must be the index of the new color (0 to 15) -;; -;; Known limitations: -;; * This function *will not work from ROM*, as it uses self-modifying code. -;; * This function requires the CPC firmware to be DISABLED. Otherwise, random crashes might happen due to side effects. -;; -;; Destroyed Register values: -;; AF, BC, DE, HL, BC', DE', HL', IX -;; -;; Required memory: -;; C-bindings - 87 bytes -;; ASM-bindings - 73 bytes -;; -;; Time Measures: -;; (start code) -;; Case | microSecs (us) | CPU Cycles -;; ---------------------------------------------------------------- -;; | 29 + (41 + 6W)H | 116 + (164 + 24W)H -;; ---------------------------------------------------------------- -;; W=2,H=16 | 2109 | 8436 -;; W=4,H=32 | 877 | 3508 -;; ---------------------------------------------------------------- -;; Asm saving | -16 | -64 -;; ---------------------------------------------------------------- -;; (end code) -;; W = *width* in bytes, H = *height* in bytes, HH = [(H-1)/8] -;; -;; Credits: -;; Original routine optimized by @Docent and discussed in CPCWiki : -;; http://www.cpcwiki.eu/forum/programming/cpctelera-colorize-sprite/ -;; -;; Thanks to all of them for their help and support. -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -.globl dc_mode0_ct - -;; Macro to convert Pixel to xAxC xBxD format -.macro convertPixel - ;; From cpct_px2byteM0 - ld bc, #dc_mode0_ct ;; [3] BC points to conversion table (dc_mode0_ct) - - ;; Compute BC += A - add c ;; [1] | C += A - ld c, a ;; [1] | - sub a ;; [1] A = 0 (preserving Carry Flag) - adc b ;; [1] | B += Carry - ld b, a ;; [1] | - - ;; A = *(BC + A) - ld a, (bc) ;; [2] A = Value stored at the table pointed by BC -.endm - - ;; Convert newColor to pixel format (E) - ld a, h ;; [1] A = H new color index - convertPixel ;; [10] | Convert into A - ld e, a ;; [1] | E = A new color : xAxC xBxD - - ;; Convert oldColor to pixel format (D) - ld a, l ;; [1] A = L old color index - convertPixel ;; [10] | Convert into A - ld d, a ;; [1] | D = A old color : xAxC xBxD - - ld c, #0x55 ;; [2] C = Mask to get pixel A : xAxC xBxD - exx ;; [1] Switch to Alternate registers - - ld__ixl_c ;; [1] IXL = C (Width) - ld c, b ;; [1] C = B (Height) - -convertLoop: - ld__b_ixl ;; [2] B = IXL (Sprite Width) - -lineLoop: - ld a, (hl) ;; [2] A = (HL) current Byte of sprite Mask - ld (de), a ;; [2] (DE) = A Copy of sprite Mask - inc hl ;; [2] Next byte sprite Color source - inc de ;; [2] Next byte sprite Color destination - ld a, (hl) ;; [2] A = (HL) current Byte of sprite Color - - exx ;; [1] Switch to Default registers - - ld l, a ;; [1] L = A current Byte of sprite : ABAB ABAB - and c ;; [2] A |= C (C = 0x55) : xBxB xBxB - - cp d ;; [1] Test if pixel (A) is the old colour to be replaced (D) - jr nz, readPixelA ;; [2/3] If not equal go to next pixel - ld a, e ;; [1] else A = new colour to set (E) - -;; Pixel Mode 0 = ABAB ABAB -readPixelA: - ld h, a ;; [1] H = A (current colorized sprite) : xBxB xBxB - ld a, l ;; [1] L = A current Byte of sprite : ABAB ABAB - rrca ;; [1] A (current byte of sprite) >> 1 : ABAB ABAB -> xABA BABA - and c ;; [2] A |= Mask (0x55) : xAxA xAxA - - cp d ;; [1] Test if pixel (A) is the old colour to be replaced (D) - jr nz, readPixelB ;; [2/3] If not equal go to next pixel - ld a, e ;; [1] else A = new colour to set (E) - -readPixelB: - rlca ;; [1] A = xAxA xAxA << 1 : AxAx AxAx - or h ;; [1] A |= H (xBxB xBxB) : ABAB ABAB - -setByte: - exx ;; [1] Switch to Alternate registers - - ld (de), a ;; [2] Update current sprite byte with pixels - inc hl ;; [2] Next byte sprite source - inc de ;; [2] Next byte sprite colorized - djnz lineLoop ;; [3] Decrement B (Width) if != 0 goto lineLoop - - dec c ;; [1] Decrement C (Height) - jr nz, convertLoop ;; [2/3] If C == O goto end - -end: - ;; Return is included in bindings \ No newline at end of file diff --git a/examples/medium/colorReplace/src/asm/sprites/colorReplace/M0/cpct_spriteMaskedColorizeM0_asmbindings.s b/examples/medium/colorReplace/src/asm/sprites/colorReplace/M0/cpct_spriteMaskedColorizeM0_asmbindings.s deleted file mode 100644 index 30440d708..000000000 --- a/examples/medium/colorReplace/src/asm/sprites/colorReplace/M0/cpct_spriteMaskedColorizeM0_asmbindings.s +++ /dev/null @@ -1,36 +0,0 @@ -;;-----------------------------LICENSE NOTICE------------------------------------ -;; This file is part of CPCtelera: An Amstrad CPC Game Engine -;; Copyright (C) 2017 Arnaud Bouche (Arnaud6128) -;; Copyright (C) 2017 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) -;; -;; This program is free software: you can redistribute it and/or modify -;; it under the terms of the GNU Lesser General Public License as published by -;; the Free Software Foundation, either version 3 of the License, or -;; (at your option) any later version. -;; -;; This program is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU Lesser General Public License for more details. -;; -;; You should have received a copy of the GNU Lesser General Public License -;; along with this program. If not, see <http://www.gnu.org/licenses/>. -;;------------------------------------------------------------------------------- -.module cpct_sprites - -.include "../../../macros/cpct_undocumentedOpcodes.s" - -;; -;; ASM bindings for <cpct_spriteMaskedColorizeM0> -;; -cpct_spriteMaskedColorizeM0_asm:: ;; Assembly entry point - - ;; GET Parameters from the stack - ld (dms_restore_ix + 2), ix ;; [6] Save IX to restore it before returning - pop hl ;; [3] HL = Return Address - -.include /cpct_spriteMaskedColorizeM0.asm/ - -dms_restore_ix: - ld ix, #0000 ;; [4] Restore IX before returning - ret ;; [3] Return to caller \ No newline at end of file diff --git a/examples/medium/colorReplace/src/asm/sprites/colorReplace/M0/cpct_spriteMaskedColorizeM0_cbindings.s b/examples/medium/colorReplace/src/asm/sprites/colorReplace/M0/cpct_spriteMaskedColorizeM0_cbindings.s deleted file mode 100644 index a2bba9de5..000000000 --- a/examples/medium/colorReplace/src/asm/sprites/colorReplace/M0/cpct_spriteMaskedColorizeM0_cbindings.s +++ /dev/null @@ -1,48 +0,0 @@ -;;-----------------------------LICENSE NOTICE------------------------------------ -;; This file is part of CPCtelera: An Amstrad CPC Game Engine -;; Copyright (C) 2017 Arnaud Bouche (Arnaud6128) -;; Copyright (C) 2017 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) -;; -;; This program is free software: you can redistribute it and/or modify -;; it under the terms of the GNU Lesser General Public License as published by -;; the Free Software Foundation, either version 3 of the License, or -;; (at your option) any later version. -;; -;; This program is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU Lesser General Public License for more details. -;; -;; You should have received a copy of the GNU Lesser General Public License -;; along with this program. If not, see <http://www.gnu.org/licenses/>. -;;------------------------------------------------------------------------------- -.module cpct_sprites - -.include "../../../macros/cpct_undocumentedOpcodes.s" - -;; -;; C bindings for <cpct_spriteMaskedColorizeM0> -;; -;; 33 us, 14 bytes -;; -_cpct_spriteMaskedColorizeM0:: - - ;; GET Parameters from the stack - ld (dms_restore_ix + 2), ix ;; [6] Save IX to restore it before returning - pop hl ;; [3] HL = Return Address - - exx - pop hl ;; [3] HL' = Source address (Sprite) - pop de ;; [3] DE' = Destination Sprite color - pop bc ;; [5] BC' = (B = Sprite Height, C = Width) - exx - - ex (sp), hl ;; [6] HL = (H = newColor, L = oldColor) - ;; ... and leave Return Address at (SP) as we don't need to restore - ;; ... stack status because callin convention is __z88dk_callee - -.include /cpct_spriteMaskedColorizeM0.asm/ - -dms_restore_ix: - ld ix, #0000 ;; [4] Restore IX before returning - ret ;; [3] Return to caller \ No newline at end of file diff --git a/examples/medium/colorReplace/src/asm/sprites/colorReplace/M1/cpct_drawSpriteColorizeM1.asm b/examples/medium/colorReplace/src/asm/sprites/colorReplace/M1/cpct_drawSpriteColorizeM1.asm deleted file mode 100644 index bcf3f88da..000000000 --- a/examples/medium/colorReplace/src/asm/sprites/colorReplace/M1/cpct_drawSpriteColorizeM1.asm +++ /dev/null @@ -1,228 +0,0 @@ -;;-----------------------------LICENSE NOTICE------------------------------------ -;; This file is part of CPCtelera: An Amstrad CPC Game Engine -;; Copyright (C) 2017 Arnaud Bouche (Arnaud6128) -;; Copyright (C) 2017 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) -;; -;; This program is free software: you can redistribute it and/or modify -;; it under the terms of the GNU Lesser General Public License as published by -;; the Free Software Foundation, either version 3 of the License, or -;; (at your option) any later version. -;; -;; This program is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU Lesser General Public License for more details. -;; -;; You should have received a copy of the GNU Lesser General Public License -;; along with this program. If not, see <http://www.gnu.org/licenses/>. -;;------------------------------------------------------------------------------- -.module cpct_sprites - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; -;; Function: cpct_drawSpriteColorizeM1 -;; -;; Directly replace a color and draw a sprite to video memory. -;; -;; C Definition: -;; void <cpct_drawSpriteColorizeM1> (void* *sprite*, void* *memory*, <u8> *width*, <u8> *height*, <u8> *oldColor*, <u8> *newColor*) __z88dk_callee; -;; -;; Input Parameters (6 bytes): -;; (2B HL') sprite - Source Sprite Pointer (array of pixel data) -;; (2B DE') memory - Destination video memory pointer -;; (1B C' ) height - Sprite Height in bytes (>0) -;; (1B B' ) width - Sprite Width in *bytes* (Beware, *not* in pixels!) -;; (1B L ) oldColor - Color to replace -;; (1B H ) newColor - New color -;; -;; Assembly call (Input parameters on registers): -;; > call cpct_drawSpriteColorizeM1_asm -;; -;; Parameter Restrictions: -;; * *sprite* must be an array containing sprite's pixels data in screen pixel format. -;; Sprite must be rectangular and all bytes in the array must be consecutive pixels, -;; starting from top-left corner and going left-to-right, top-to-bottom down to the -;; bottom-right corner. Total amount of bytes in pixel array should be *width* x *height*. -;; * *memory* could be any place in memory, inside or outside current video memory. It -;; will be equally treated as video memory (taking into account CPC's video memory -;; disposition). This lets you copy sprites to software or hardware backbuffers, and -;; not only video memory. -;; * *width* must be the width of the sprite *in bytes*. Always remember that the width must be -;; expressed in bytes and *not* in pixels. -;; The correspondence is mode 1 : 1 byte = 4 pixels -;; * *height* must be the height of the sprite in bytes, and must be greater than 0. -;; There is no practical upper limit to this value. Height of a sprite in -;; bytes and pixels is the same value, as bytes only group consecutive pixels in -;; the horizontal space. -;; * *oldColor* must be the index of color (0 to 3) to replace -;; * *newColor* must be the index of the new color (0 to 3) -;; -;; Known limitations: -;; * This function does not do any kind of boundary check or clipping. If you -;; try to draw sprites on the frontier of your video memory or screen buffer -;; if might potentially overwrite memory locations beyond boundaries. This -;; could cause your program to behave erratically, hang or crash. Always -;; take the necessary steps to guarantee that you are drawing inside screen -;; or buffer boundaries. -;; * As this function receives a byte-pointer to memory, it can only -;; draw byte-sized and byte-aligned sprites. This means that the box cannot -;; start on non-byte aligned pixels (like odd-pixels, for instance) and -;; their sizes must be a multiple of a byte (2 in mode 0, 4 in mode 1 and -;; 8 in mode 2). -;; * This function *will not work from ROM*, as it uses self-modifying code. -;; * This function requires the CPC firmware to be DISABLED. Otherwise, random crashes might happen due to side effects. -;; -;; Destroyed Register values: -;; AF, BC, DE, HL, BC', DE', HL', IX -;; -;; Required memory: -;; C-bindings - 116 bytes -;; ASM-bindings - 103 bytes -;; -;; Time Measures: -;; (start code) -;; Case | microSecs (us) | CPU Cycles -;; ---------------------------------------------------------------- -;; | 29 + (36 + 61W)H | 116 + (144 + 244W)H -;; ---------------------------------------------------------------- -;; W=2,H=16 | 2557 | 10228 -;; W=4,H=32 | 8989 | 35956 -;; ---------------------------------------------------------------- -;; Asm saving | -16 | -64 -;; ---------------------------------------------------------------- -;; (end code) -;; W = *width* in bytes, H = *height* in bytes -;; -;; Credits: -;; Original routine optimized by @Docent and discussed in CPCWiki : -;; http://www.cpcwiki.eu/forum/programming/cpctelera-colorize-sprite/ -;; -;; Thanks to all of them for their help and support. -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -.globl dc_mode1_ct - -;; Macro to convert color to pixel Mode1 : Axxx Axxx -.macro convertPixel ;; From cpct_px2byteM1 - ld bc, #dc_mode1_ct ;; [3] BC points to conversion table (dc_mode1_ct) - - ;; Compute BC += A - add c ;; [1] | C += A - ld c, a ;; [1] | - sub a ;; [1] A = 0 (preserving Carry Flag) - adc b ;; [1] | B += Carry - ld b, a ;; [1] | - - ;; A = *(BC + A) - ld a, (bc) ;; [2] A = Value stored at the table pointed by BC -.endm - - ;; Convert newColor to pixel format (E) - ld a, h ;; [1] A = H new color index - convertPixel ;; [10] | Convert into A - ld e, a ;; [1] | E = A new color : Axxx Axxx - - ;; Convert oldColor to pixel format (D) - ld a, l ;; [1] A = L old color index - convertPixel ;; [10] | Convert into A - ld d, a ;; [1] | D = A old color : Axxx Axxx - - ld c, #0x88 ;; [2] C = Mask to get pixel A : Axxx Axxx - exx ;; [1] Switch to Alternate registers - - ld__ixl_c ;; [1] IXL = C (Width) - ld c, b ;; [1] C = B (Height) - -convertLoop: - ld (startLine), de ;; [6] Store DE start line (DestMem) - ld__b_ixl ;; [2] B = IXL (Sprite Width) - -lineLoop: - ld a, (hl) ;; [2] A = (HL) current Byte of sprite - exx ;; [1] Switch to Default registers - - ld l, a ;; [1] L = A current Byte of sprite : ABCD ABCD - and c ;; [2] A |= C (C = 0x88) : Axxx Axxx - - cp d ;; [1] Test if pixel (A) is the old colour to be replaced (D) - jr nz, readPixelA ;; [2/3] If not equal go to next pixel - ld a, e ;; [1] else A = new colour to set (E) - -readPixelA: - ld h, a ;; [1] H = A (current colorized sprite) : Axxx Axxx - - sla l ;; [2] L (current byte of sprite) << 1 : ABCD ABCD -> BCDx BCDx - ld a, l ;; [1] A = L : BCDx BCDx - and c ;; [2] A |= Mask (0x88) : Bxxx Bxxx - - cp d ;; [1] Test if pixel (A) is the old colour to be replaced (D) - jr nz, readPixelB ;; [2/3] If not equal go to next pixel - ld a, e ;; [1] else A = new colour to set (E) - -readPixelB: - rrca ;; [1] A = Axxx Axxx >> 1 : xBxx xBxx - or h ;; [1] A |= H (color byte) : Axxx Axxx - ld h, a ;; [1] H = A : ABxx ABxx - - sla l ;; [2] L ( BCDx BCDx) << 1 : CDxx CDxx - ld a, l ;; [1] A = L : CDxx CDxx - and c ;; [1] A |= C (C = 0x88) : Cxxx Cxxx - - cp d ;; [1] Test if pixel (A) is the old colour to be replaced (D) - jr nz, readPixelC ;; [2/3] If not equal go to next pixel - ld a, e ;; [1] else A = new colour to set (E) - -readPixelC: - rrca ;; [1] A = Axxx Axxx >> 1 : xBxx xBxx - rrca ;; [1] A = xxCx xxCx << 1 : xxCx xxCx - or h ;; [1] A |= H (ABxx ABxx) : ABCx ABCx - ld h, a ;; [1] H = A : ABCx ABCx - - sla l ;; [2] L (BCDx BCDx) << 1 : Dxxx Dxxx - ld a, l ;; [1] A = L : Dxxx Dxxx - and c ;; [1] A |= C (C = 0x88) : Dxxx Dxxx - - cp d ;; [1] Test if pixel (A) is the old colour to be replaced (D) - jr nz, readPixelD ;; [2/3] If not equal go to next pixel - ld a, e ;; [1] else A = new colour to set (E) - -readPixelD: - rrca ;; [1] A = Axxx Axxx >> 1 : xBxx xBxx - rrca ;; [1] A = xBxx xBxx >> 1 : xxCx xxCx - rrca ;; [1] A = xxCx xxxx >> 1 : xxxD xxxD - or h ;; [1] A |= H (ABCx ABCx) : ABCD ABCD - - exx ;; [1] Switch to Alternate registers - - ld (de), a ;; [2] Update current sprite byte with pixels - inc hl ;; [2] Next byte sprite source - inc de ;; [2] Next byte sprite colorized - djnz lineLoop ;; [3] Decrement B (Width) if B != 0 goto lineLoop - - dec c ;; [1] Decrement C (Height) - jr z, end ;; [2/3] If C == O goto end - -startLine = .+1 ;; Placeholder for the Start line adress - ld de, #0000 ;; [3] DE = Start Line - - ld a, d ;; [1] Start of next pixel line normally is 0x0800 bytes away. - add #0x08 ;; [2] so we add it to DE (just by adding 0x08 to D) - ld d, a ;; [1] - and #0x38 ;; [2] We check if we have crossed memory boundary (every 8 pixel lines).. - - jr nz, convertLoop ;; [2/3] .. by checking the 4 bits that identify present memory line. - ;; .... If 0, we have crossed boundaries - -dms_sprite_8bit_boundary_crossed: - ld a, e ;; [1] DE = DE + 0xC050h - add #0x50 ;; [2] -- Relocate DE pointer to the start of the next pixel line: - ld e, a ;; [1] -- DE is moved forward 3 memory banks plus 50 bytes (4000h * 3) - ld a, d ;; [1] -- which effectively is the same as moving it 1 bank backwards and then - adc #0xC0 ;; [2] -- 50 bytes forwards (which is what we want to move it to the next pixel line) - ld d, a ;; [1] -- Calculations are made with 8 bit maths as it is faster than other alternatives here - - jr convertLoop ;; [3] Jump to continue with next pixel line - -end: - ;; Return is included in bindings - diff --git a/examples/medium/colorReplace/src/asm/sprites/colorReplace/M1/cpct_drawSpriteColorizeM1_asmbindings.s b/examples/medium/colorReplace/src/asm/sprites/colorReplace/M1/cpct_drawSpriteColorizeM1_asmbindings.s deleted file mode 100644 index 44ca0f2b0..000000000 --- a/examples/medium/colorReplace/src/asm/sprites/colorReplace/M1/cpct_drawSpriteColorizeM1_asmbindings.s +++ /dev/null @@ -1,35 +0,0 @@ -;;-----------------------------LICENSE NOTICE------------------------------------ -;; This file is part of CPCtelera: An Amstrad CPC Game Engine -;; Copyright (C) 2017 Arnaud Bouche (Arnaud6128) -;; Copyright (C) 2017 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) -;; -;; This program is free software: you can redistribute it and/or modify -;; it under the terms of the GNU Lesser General Public License as published by -;; the Free Software Foundation, either version 3 of the License, or -;; (at your option) any later version. -;; -;; This program is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU Lesser General Public License for more details. -;; -;; You should have received a copy of the GNU Lesser General Public License -;; along with this program. If not, see <http://www.gnu.org/licenses/>. -;;------------------------------------------------------------------------------- -.module cpct_sprites - -.include "../../../macros/cpct_undocumentedOpcodes.s" - -;; -;; ASM bindings for <cpct_drawSpriteColorizeM1> -;; -cpct_drawSpriteColorizeM1_asm:: ;; Assembly entry point - -;; GET Parameters from the stack -ld (dms_restore_ix + 2), ix ;; [6] Save IX to restore it before returning - -.include /cpct_drawSpriteColorizeM1.asm/ - -dms_restore_ix: - ld ix, #0000 ;; [4] Restore IX before returning - ret \ No newline at end of file diff --git a/examples/medium/colorReplace/src/asm/sprites/colorReplace/M1/cpct_drawSpriteColorizeM1_cbindings.s b/examples/medium/colorReplace/src/asm/sprites/colorReplace/M1/cpct_drawSpriteColorizeM1_cbindings.s deleted file mode 100644 index 22798d0f3..000000000 --- a/examples/medium/colorReplace/src/asm/sprites/colorReplace/M1/cpct_drawSpriteColorizeM1_cbindings.s +++ /dev/null @@ -1,48 +0,0 @@ -;;-----------------------------LICENSE NOTICE------------------------------------ -;; This file is part of CPCtelera: An Amstrad CPC Game Engine -;; Copyright (C) 2017 Arnaud Bouche (Arnaud6128) -;; Copyright (C) 2017 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) -;; -;; This program is free software: you can redistribute it and/or modify -;; it under the terms of the GNU Lesser General Public License as published by -;; the Free Software Foundation, either version 3 of the License, or -;; (at your option) any later version. -;; -;; This program is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU Lesser General Public License for more details. -;; -;; You should have received a copy of the GNU Lesser General Public License -;; along with this program. If not, see <http://www.gnu.org/licenses/>. -;;------------------------------------------------------------------------------- -.module cpct_sprites - -.include "../../../macros/cpct_undocumentedOpcodes.s" - -;; -;; C bindings for <cpct_drawSpriteColorizeM1> -;; -;; 31 us, 13 bytes -;; -_cpct_drawSpriteColorizeM1:: - - ;; GET Parameters from the stack - ld (dms_restore_ix + 2), ix ;; [6] Save IX to restore it before returning - pop hl ;; [3] HL = Return Address - - exx - pop hl ;; [3] HL' = Source address (Sprite) - pop de ;; [3] DE' = Destination Memory - pop bc ;; [5] BC' = (B = Sprite Height, C = Width) - exx - - ex (sp), hl ;; [6] HL = (H = newColor, L = oldColor) - ;; ... and leave Return Address at (SP) as we don't need to restore - ;; ... stack status because callin convention is __z88dk_callee - -.include /cpct_drawSpriteColorizeM1.asm/ - -dms_restore_ix: - ld ix, #0000 ;; [4] Restore IX before returning - ret ;; [3] Return to caller \ No newline at end of file diff --git a/examples/medium/colorReplace/src/asm/sprites/colorReplace/M1/cpct_drawSpriteMaskedAlignedColorizeM1.asm b/examples/medium/colorReplace/src/asm/sprites/colorReplace/M1/cpct_drawSpriteMaskedAlignedColorizeM1.asm deleted file mode 100644 index 6d2cda5ee..000000000 --- a/examples/medium/colorReplace/src/asm/sprites/colorReplace/M1/cpct_drawSpriteMaskedAlignedColorizeM1.asm +++ /dev/null @@ -1,239 +0,0 @@ -;;-----------------------------LICENSE NOTICE------------------------------------ -;; This file is part of CPCtelera: An Amstrad CPC Game Engine -;; Copyright (C) 2017 Arnaud Bouche (Arnaud6128) -;; Copyright (C) 2017 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) -;; -;; This program is free software: you can redistribute it and/or modify -;; it under the terms of the GNU Lesser General Public License as published by -;; the Free Software Foundation, either version 3 of the License, or -;; (at your option) any later version. -;; -;; This program is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU Lesser General Public License for more details. -;; -;; You should have received a copy of the GNU Lesser General Public License -;; along with this program. If not, see <http://www.gnu.org/licenses/>. -;;------------------------------------------------------------------------------- -.module cpct_sprites - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; -;; Function: cpct_drawSpriteMaskedAlignedColorizeM1 -;; -;; Directly replace a color and draw a sprite Masked Aligned to video memory. -;; -;; C Definition: -;; void <cpct_drawSpriteMaskedAlignedColorizeM1> (void* *sprite*, void* *memory*, <u8> *width*, <u8> *height*, -;; <u8> *oldColor*, <u8> *newColor*, <u8*> *pmasktable*) __z88dk_callee; -;; -;; Input Parameters (10 bytes): -;; (2B HL') sprite - Source Sprite Pointer (array of pixel data) -;; (2B DE') memory - Destination video memory pointer -;; (1B C' ) height - Sprite Height in bytes (>0) -;; (1B B' ) width - Sprite Width in *bytes* (Beware, *not* in pixels!) -;; (1B E ) oldColor - Color to replace -;; (1B D ) newColor - New color -;; (2B HL) pmasktable - Pointer to the aligned mask table used to create transparency -;; -;; Assembly call (Input parameters on registers): -;; > call cpct_drawSpriteMaskedAlignedColorizeM1_asm -;; -;; Parameter Restrictions: -;; * *sprite* must be an array containing sprite's pixels data in screen pixel format -;; Sprite must be rectangular and all bytes in the array must be consecutive pixels, -;; starting from top-left corner and going left-to-right, top-to-bottom down to the -;; bottom-right corner. Total amount of bytes in pixel array should be *width* x *height*. -;; * *memory* could be any place in memory, inside or outside current video memory. It -;; will be equally treated as video memory (taking into account CPC's video memory -;; disposition). This lets you copy sprites to software or hardware backbuffers, and -;; not only video memory. -;; * *width* must be the width of the sprite *in bytes*. Always remember that the width must be -;; expressed in bytes and *not* in pixels. -;; The correspondence is mode 0 : 1 byte = 4 pixels -;; * *height* must be the height of the sprite in bytes, and must be greater than 0. -;; There is no practical upper limit to this value. Height of a sprite in -;; bytes and pixels is the same value, as bytes only group consecutive pixels in -;; the horizontal space. -;; * *oldColor* must be the index of color (0 to 3) to replace -;; * *newColor* must be the index of the new color (0 to 3) -;; -;; Known limitations: -;; * This function does not do any kind of boundary check or clipping. If you -;; try to draw sprites on the frontier of your video memory or screen buffer -;; if might potentially overwrite memory locations beyond boundaries. This -;; could cause your program to behave erratically, hang or crash. Always -;; take the necessary steps to guarantee that you are drawing inside screen -;; or buffer boundaries. -;; * As this function receives a byte-pointer to memory, it can only -;; draw byte-sized and byte-aligned sprites. This means that the box cannot -;; start on non-byte aligned pixels (like odd-pixels, for instance) and -;; their sizes must be a multiple of a byte (2 in mode 0, 4 in mode 1 and -;; 8 in mode 2). -;; * This function *will not work from ROM*, as it uses self-modifying code. -;; * This function requires the CPC firmware to be DISABLED. Otherwise, random crashes might happen due to side effects. -;; -;; Destroyed Register values: -;; AF, BC, DE, HL, BC', DE', HL', IX -;; -;; Required memory: -;; C-bindings - 133 bytes -;; ASM-bindings - 117 bytes -;; -;; Time Measures: -;; (start code) -;; Case | microSecs (us) | CPU Cycles -;; ---------------------------------------------------------------- -;; | 32 + (33 + 75W)H | 128 + (132 + 300W)H -;; ---------------------------------------------------------------- -;; W=2,H=16 | 2960 | 11840 -;; W=4,H=32 | 10688 | 42752 -;; ---------------------------------------------------------------- -;; Asm saving | -16 | -64 -;; ---------------------------------------------------------------- -;; (end code) -;; W = *width* in bytes, H = *height* in bytes, HH = [(H-1)/8] -;; -;; Credits: -;; Original routine optimized by @Docent and discussed in CPCWiki : -;; http://www.cpcwiki.eu/forum/programming/cpctelera-colorize-sprite/ -;; -;; Thanks to all of them for their help and support. -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -.globl dc_mode1_ct - -;; Macro to convert color to pixel Mode1 : Axxx Axxx -.macro convertPixel ;; From cpct_px2byteM1 - ld bc, #dc_mode1_ct ;; [3] BC points to conversion table (dc_mode1_ct) - - ;; Compute BC += A - add c ;; [1] | C += A - ld c, a ;; [1] | - sub a ;; [1] A = 0 (preserving Carry Flag) - adc b ;; [1] | B += Carry - ld b, a ;; [1] | - - ;; A = *(BC + A) - ld a, (bc) ;; [2] A = Value stored at the table pointed by HL -.endm - - ;; Convert newColor to pixel format (E) - ld a, h ;; [1] A = H new color index - convertPixel ;; [10] | Convert into A - ld e, a ;; [1] | E = A new color : Axxx Axxx - - ;; Convert oldColor to pixel format (D) - ld a, l ;; [1] A = L old color index - convertPixel ;; [10] | Convert into A - ld d, a ;; [1] | D = A old color : Axxx Axxx - - ld c, #0x88 ;; [2] C = Mask to get pixel A : Axxx Axxx - exx ;; [1] Switch to Alternate registers - - ld__ixl_c ;; [1] IXL = C (Width) - ld c, b ;; [1] C = B (Height) - -convertLoop: - push de ;; [4] Store DE start line (DestMem) - ld__b_ixl ;; [2] B = IXL (Sprite Width) - -lineLoop: - ld a, (hl) ;; [2] A = (HL) current Byte of sprite Mask - exx ;; [1] Switch to Default registers - - ld l, a ;; [1] L = A current Byte of sprite : ABCD ABCD - and c ;; [2] A |= C (C = 0x88) : Axxx Axxx - - cp d ;; [1] Test if pixel (A) is the old colour to be replaced (D) - jr nz, readPixelA ;; [2/3] If not equal go to next pixel - ld a, e ;; [1] else A = new colour to set (E) - -readPixelA: - ld h, a ;; [1] H = A (current colorized sprite) : Axxx Axxx - - sla l ;; [2] L (current byte of sprite) << 1 : ABCD ABCD -> BCDx BCDx - ld a, l ;; [1] A = L : BCDx BCDx - and c ;; [2] A |= Mask (0x88) : Bxxx Bxxx - - cp d ;; [1] Test if pixel (A) is the old colour to be replaced (D) - jr nz, readPixelB ;; [2/3] If not equal go to next pixel - ld a, e ;; [1] else A = new colour to set (E) - -readPixelB: - rrca ;; [1] A = Axxx Axxx >> 1 : xBxx xBxx - or h ;; [1] A |= H (color byte) : Axxx Axxx - ld h, a ;; [1] H = A : ABxx ABxx - - sla l ;; [2] L ( BCDx BCDx) << 1 : CDxx CDxx - ld a, l ;; [1] A = L : CDxx CDxx - and c ;; [1] A |= C (C = 0x88) : Cxxx Cxxx - - cp d ;; [1] Test if pixel (A) is the old colour to be replaced (D) - jr nz, readPixelC ;; [2/3] If not equal go to next pixel - ld a, e ;; [1] else A = new colour to set (E) - -readPixelC: - rrca ;; [1] A = Axxx Axxx >> 1 : xBxx xBxx - rrca ;; [1] A = xxCx xxCx << 1 : xxCx xxCx - or h ;; [1] A |= H (ABxx ABxx) : ABCx ABCx - ld h, a ;; [1] H = A : ABCx ABCx - - sla l ;; [2] L (BCDx BCDx) << 1 : Dxxx Dxxx - ld a, l ;; [1] A = L : Dxxx Dxxx - and c ;; [1] A |= C (C = 0x88) : Dxxx Dxxx - - cp d ;; [1] Test if pixel (A) is the old colour to be replaced (D) - jr nz, readPixelD ;; [2/3] If not equal go to next pixel - ld a, e ;; [1] else A = new colour to set (E) - -readPixelD: - rrca ;; [1] A = Axxx Axxx >> 1 : xBxx xBxx - rrca ;; [1] A = xBxx xBxx >> 1 : xxCx xxCx - rrca ;; [1] A = xxCx xxxx >> 1 : xxxD xxxD - or h ;; [1] A |= H (ABCx ABCx) : ABCD ABCD - - exx ;; [1] Switch to Alternate registers - -drawByte: - push hl ;; [4] Store HL (current byte sprite source) - ld h, b ;; [1] H = B (Masked table adress High Byte) - ld l, a ;; [1] Access mask table element (table must be 256-byte aligned) - ld a, (de) ;; [2] Get the value of the byte of the screen where we are going to draw - and (hl) ;; [2] Erase background part that is to be overwritten (Mask step 1) - or l ;; [1] Add up background and sprite information in one byte (Mask step 2) - ld (de), a ;; [2] Save modified background + sprite data information into memory - pop hl ;; [3] Recover HL (current byte sprite source) - - inc hl ;; [2] Next byte sprite source - inc de ;; [2] Next byte sprite colorized - djnz lineLoop ;; [3] Decrement B (Width) if B != 0 goto lineLoop - - dec c ;; [1] Decrement C (Height) - jr z, end ;; [2/3] If C == O goto end - - pop de ;; [3] Restore DE start line (DestMem - - ld a, d ;; [1] Start of next pixel line normally is 0x0800 bytes away. - add #0x08 ;; [2] so we add it to DE (just by adding 0x08 to D) - ld d, a ;; [1] - and #0x38 ;; [2] We check if we have crossed memory boundary (every 8 pixel lines).. - - jr nz, convertLoop ;; [2/3] .. by checking the 4 bits that identify present memory line. - ;; .... If 0, we have crossed boundaries - -dms_sprite_8bit_boundary_crossed: - ld a, e ;; [1] DE = DE + 0xC050h - add #0x50 ;; [2] -- Relocate DE pointer to the start of the next pixel line: - ld e, a ;; [1] -- DE is moved forward 3 memory banks plus 50 bytes (4000h * 3) - ld a, d ;; [1] -- which effectively is the same as moving it 1 bank backwards and then - adc #0xC0 ;; [2] -- 50 bytes forwards (which is what we want to move it to the next pixel line) - ld d, a ;; [1] -- Calculations are made with 8 bit maths as it is faster than other alternatives here - - jr convertLoop ;; [3] Jump to continue with next pixel line - -end: - pop de ;; [3] Empty stack by getting last element (DestMem) - ;; Return is included in bindings - diff --git a/examples/medium/colorReplace/src/asm/sprites/colorReplace/M1/cpct_drawSpriteMaskedAlignedColorizeM1_asmbindings.s b/examples/medium/colorReplace/src/asm/sprites/colorReplace/M1/cpct_drawSpriteMaskedAlignedColorizeM1_asmbindings.s deleted file mode 100644 index db02086d7..000000000 --- a/examples/medium/colorReplace/src/asm/sprites/colorReplace/M1/cpct_drawSpriteMaskedAlignedColorizeM1_asmbindings.s +++ /dev/null @@ -1,36 +0,0 @@ -;;-----------------------------LICENSE NOTICE------------------------------------ -;; This file is part of CPCtelera: An Amstrad CPC Game Engine -;; Copyright (C) 2017 Arnaud Bouche (Arnaud6128) -;; Copyright (C) 2017 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) -;; -;; This program is free software: you can redistribute it and/or modify -;; it under the terms of the GNU Lesser General Public License as published by -;; the Free Software Foundation, either version 3 of the License, or -;; (at your option) any later version. -;; -;; This program is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU Lesser General Public License for more details. -;; -;; You should have received a copy of the GNU Lesser General Public License -;; along with this program. If not, see <http://www.gnu.org/licenses/>. -;;------------------------------------------------------------------------------- -.module cpct_sprites - -.include "../../../macros/cpct_undocumentedOpcodes.s" - -;; -;; ASM bindings for <cpct_drawSpriteMaskedAlignedColorizeM1> -;; -cpct_drawSpriteMaskedAlignedColorizeM1_asm:: ;; Assembly entry point - - ;; GET Parameters from the stack - ld (dms_restore_ix + 2), ix ;; [6] Save IX to restore it before returning - pop hl ;; [3] HL = Return Address - -.include /cpct_drawSpriteMaskedAlignedColorizeM1.asm/ - -dms_restore_ix: - ld ix, #0000 ;; [4] Restore IX before returning - ret ;; [3] Return to caller \ No newline at end of file diff --git a/examples/medium/colorReplace/src/asm/sprites/colorReplace/M1/cpct_drawSpriteMaskedAlignedColorizeM1_cbindings.s b/examples/medium/colorReplace/src/asm/sprites/colorReplace/M1/cpct_drawSpriteMaskedAlignedColorizeM1_cbindings.s deleted file mode 100644 index f0b0a2130..000000000 --- a/examples/medium/colorReplace/src/asm/sprites/colorReplace/M1/cpct_drawSpriteMaskedAlignedColorizeM1_cbindings.s +++ /dev/null @@ -1,53 +0,0 @@ -;;-----------------------------LICENSE NOTICE------------------------------------ -;; This file is part of CPCtelera: An Amstrad CPC Game Engine -;; Copyright (C) 2017 Arnaud Bouche (Arnaud6128) -;; Copyright (C) 2017 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) -;; -;; This program is free software: you can redistribute it and/or modify -;; it under the terms of the GNU Lesser General Public License as published by -;; the Free Software Foundation, either version 3 of the License, or -;; (at your option) any later version. -;; -;; This program is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU Lesser General Public License for more details. -;; -;; You should have received a copy of the GNU Lesser General Public License -;; along with this program. If not, see <http://www.gnu.org/licenses/>. -;;------------------------------------------------------------------------------- -.module cpct_sprites - -.include "../../../macros/cpct_undocumentedOpcodes.s" - -;; -;; C bindings for <cpct_drawSpriteMaskedAlignedColorizeM1> -;; -;; 39 us, 16 bytes -;; -_cpct_drawSpriteMaskedAlignedColorizeM1:: - - ;; GET Parameters from the stack - ld (dms_restore_ix + 2), ix ;; [6] Save IX to restore it before returning - pop hl ;; [3] HL = Return Address - - exx ;; [1] Switch to Alternate registers - pop hl ;; [3] HL' = Source address (Sprite) - pop de ;; [3] DE' = Destination Memory - pop bc ;; [5] BC' = (B = Sprite Height, C = Width) - - exx ;; [1] Switch to Default registers - pop de ;; [3] DE = (D = newColor, E = oldColor) - - ex (sp), hl ;; [6] HL = Table Mask address - ;; ... and leave Return Address at (SP) as we don't need to restore - ;; ... stack status because callin convention is __z88dk_callee - - ex de, hl ;; [1] HL <-> DE - - -.include /cpct_drawSpriteMaskedAlignedColorizeM1.asm/ - -dms_restore_ix: - ld ix, #0000 ;; [4] Restore IX before returning - ret ;; [3] Return to caller \ No newline at end of file diff --git a/examples/medium/colorReplace/src/asm/sprites/colorReplace/M1/cpct_drawSpriteMaskedColorizeM1.asm b/examples/medium/colorReplace/src/asm/sprites/colorReplace/M1/cpct_drawSpriteMaskedColorizeM1.asm deleted file mode 100644 index c96a67928..000000000 --- a/examples/medium/colorReplace/src/asm/sprites/colorReplace/M1/cpct_drawSpriteMaskedColorizeM1.asm +++ /dev/null @@ -1,246 +0,0 @@ -;;-----------------------------LICENSE NOTICE------------------------------------ -;; This file is part of CPCtelera: An Amstrad CPC Game Engine -;; Copyright (C) 2017 Arnaud Bouche (Arnaud6128) -;; Copyright (C) 2017 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) -;; -;; This program is free software: you can redistribute it and/or modify -;; it under the terms of the GNU Lesser General Public License as published by -;; the Free Software Foundation, either version 3 of the License, or -;; (at your option) any later version. -;; -;; This program is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU Lesser General Public License for more details. -;; -;; You should have received a copy of the GNU Lesser General Public License -;; along with this program. If not, see <http://www.gnu.org/licenses/>. -;;------------------------------------------------------------------------------- -.module cpct_sprites - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; -;; Function: cpct_drawSpriteMaskedColorizeM1 -;; -;; Directly replace a color and draw a sprite Masked to video memory. -;; -;; C Definition: -;; void <cpct_drawSpriteMaskedColorizeM1> (void* *sprite*, void* *memory*, <u8> *width*, <u8> *height*, <u8> *oldColor*, <u8> *newColor*) __z88dk_callee; -;; -;; Input Parameters (8 bytes): -;; (2B HL') sprite - Source Sprite Pointer (array of pixel data) -;; (2B DE') memory - Destination video memory pointer -;; (1B C' ) height - Sprite Height in bytes (>0) -;; (1B B' ) width - Sprite Width in *bytes* (Beware, *not* in pixels!) -;; (1B L ) oldColor - Color to replace -;; (1B H ) newColor - New color -;; -;; Assembly call (Input parameters on registers): -;; > call cpct_drawSpriteMaskedColorizeM1_asm -;; -;; Parameter Restrictions: -;; * *sprite* must be an array containing sprite's pixels data in screen pixel format -;; along with mask data. Each mask byte will contain enabled bits as those that should -;; be picked from the background (transparent) and disabled bits for those that will -;; be printed from sprite colour data. Each mask data byte must precede its associated -;; colour data byte. -;; Sprite must be rectangular and all bytes in the array must be consecutive pixels, -;; starting from top-left corner and going left-to-right, top-to-bottom down to the -;; bottom-right corner. Total amount of bytes in pixel array should be -;; 2 x *width* x *height* (mask data doubles array size). -;; * *memory* could be any place in memory, inside or outside current video memory. It -;; will be equally treated as video memory (taking into account CPC's video memory -;; disposition). This lets you copy sprites to software or hardware backbuffers, and -;; not only video memory. -;; * *width* must be the width of the sprite *in bytes*. Always remember that the width must be -;; expressed in bytes and *not* in pixels. -;; The correspondence is mode 0 : 1 byte = 4 pixels -;; * *height* must be the height of the sprite in bytes, and must be greater than 0. -;; There is no practical upper limit to this value. Height of a sprite in -;; bytes and pixels is the same value, as bytes only group consecutive pixels in -;; the horizontal space. -;; * *oldColor* must be the index of color (0 to 3) to replace -;; * *newColor* must be the index of the new color (0 to 3) -;; -;; Known limitations: -;; * This function does not do any kind of boundary check or clipping. If you -;; try to draw sprites on the frontier of your video memory or screen buffer -;; if might potentially overwrite memory locations beyond boundaries. This -;; could cause your program to behave erratically, hang or crash. Always -;; take the necessary steps to guarantee that you are drawing inside screen -;; or buffer boundaries. -;; * As this function receives a byte-pointer to memory, it can only -;; draw byte-sized and byte-aligned sprites. This means that the box cannot -;; start on non-byte aligned pixels (like odd-pixels, for instance) and -;; their sizes must be a multiple of a byte (2 in mode 0, 4 in mode 1 and -;; 8 in mode 2). -;; * This function *will not work from ROM*, as it uses self-modifying code. -;; * This function requires the CPC firmware to be DISABLED. Otherwise, random crashes might happen due to side effects. -;; -;; Destroyed Register values: -;; AF, BC, DE, HL, BC', DE', HL', IX -;; -;; Required memory: -;; C-bindings - 142 bytes -;; ASM-bindings - 129 bytes -;; -;; Time Measures: -;; (start code) -;; Case | microSecs (us) | CPU Cycles -;; ---------------------------------------------------------------- -;; | 29 + (36 + 93W)H | 116 + (144 + 372W)H -;; ---------------------------------------------------------------- -;; W=2,H=16 | 3581 | 14324 -;; W=4,H=32 | 13085 | 52340 -;; ---------------------------------------------------------------- -;; Asm saving | -16 | -64 -;; ---------------------------------------------------------------- -;; (end code) -;; W = *width* in bytes, H = *height* in bytes -;; -;; Credits: -;; Original routine optimized by @Docent and discussed in CPCWiki : -;; http://www.cpcwiki.eu/forum/programming/cpctelera-colorize-sprite/ -;; -;; Thanks to all of them for their help and support. -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -.globl dc_mode1_ct - -;; Macro to convert color to pixel Mode1 : Axxx Axxx -.macro convertPixel ;; From cpct_px2byteM1 - ld bc, #dc_mode1_ct ;; [3] BC points to conversion table (dc_mode1_ct) - - ;; Compute BC += A - add c ;; [1] | C += A - ld c, a ;; [1] | - sub a ;; [1] A = 0 (preserving Carry Flag) - adc b ;; [1] | B += Carry - ld b, a ;; [1] | - - ;; A = *(BC + A) - ld a, (bc) ;; [2] A = Value stored at the table pointed by BC -.endm - - ;; Convert newColor to pixel format (E) - ld a, h ;; [1] A = H new color index - convertPixel ;; [10] | Convert into A - ld e, a ;; [1] | E = A new color : Axxx Axxx - - ;; Convert oldColor to pixel format (D) - ld a, l ;; [1] A = L old color index - convertPixel ;; [10] | Convert into A - ld d, a ;; [1] | D = A old color : Axxx Axxx - - ld c, #0x88 ;; [2] C = First Mask to get pixel A : Axxx Axxx - exx ;; [1] Switch to Alternate registers - - ld__ixl_c ;; [1] IXL = C (Width) - ld c, b ;; [1] C = B (Height) - -convertLoop: - ld (startLine), de ;; [6] Store DE start line (DestMem) - ld__b_ixl ;; [2] B = IXL (Sprite Width) - -lineLoop: - inc hl ;; [2] Next byte sprite Color source - ld a, (hl) ;; [2] A = (HL) current Byte of sprite Color - dec hl ;; [2] Previous byte sprite Mask source - - exx ;; [1] Switch to Default registers - - ld l, a ;; [1] L = A current Byte of sprite : ABCD ABCD - - and c ;; [2] A |= C (C = 0x88) : Axxx Axxx - - cp d ;; [1] Test if pixel (A) is the old colour to be replaced (D) - jr nz, readPixelA ;; [2/3] If not equal go to next pixel - ld a, e ;; [1] else A = new colour to set (E) - -readPixelA: - ld h, a ;; [1] H = A (current colorized sprite) : Axxx Axxx - - sla l ;; [2] L (current byte of sprite) << 1 : ABCD ABCD -> BCDx BCDx - ld a, l ;; [1] A = L : BCDx BCDx - and c ;; [2] A |= Mask (0x88) : Bxxx Bxxx - - cp d ;; [1] Test if pixel (A) is the old colour to be replaced (D) - jr nz, readPixelB ;; [2/3] If not equal go to next pixel - ld a, e ;; [1] else A = new colour to set (E) - -readPixelB: - rrca ;; [1] A = Axxx Axxx >> 1 : xBxx xBxx - or h ;; [1] A |= H (color byte) : Axxx Axxx - ld h, a ;; [1] H = A : ABxx ABxx - - sla l ;; [2] L ( BCDx BCDx) << 1 : CDxx CDxx - ld a, l ;; [1] A = L : CDxx CDxx - and c ;; [1] A |= C (C = 0x88) : Cxxx Cxxx - - cp d ;; [1] Test if pixel (A) is the old colour to be replaced (D) - jr nz, readPixelC ;; [2/3] If not equal go to next pixel - ld a, e ;; [1] else A = new colour to set (E) - -readPixelC: - rrca ;; [1] A = Axxx Axxx >> 1 : xBxx xBxx - rrca ;; [1] A = xxCx xxCx << 1 : xxCx xxCx - or h ;; [1] A |= H (ABxx ABxx) : ABCx ABCx - ld h, a ;; [1] H = A : ABCx ABCx - - sla l ;; [2] L (BCDx BCDx) << 1 : Dxxx Dxxx - ld a, l ;; [1] A = L : Dxxx Dxxx - and c ;; [1] A |= C (C = 0x88) : Dxxx Dxxx - - cp d ;; [1] Test if pixel (A) is the old colour to be replaced (D) - jr nz, readPixelD ;; [2/3] If not equal go to next pixel - ld a, e ;; [1] else A = new colour to set (E) - -readPixelD: - rrca ;; [1] A = Axxx Axxx >> 1 : xBxx xBxx - rrca ;; [1] A = xBxx xBxx >> 1 : xxCx xxCx - rrca ;; [1] A = xxCx xxxx >> 1 : xxxD xxxD - or h ;; [1] A |= H (ABCx ABCx) : ABCD ABCD - - exx ;; [1] Switch to Alternate registers - -drawByte: - ld (sprite_color), a ;; [4] sprite_color = A (Sprite Byte) - - ld a, (de) ;; [2] Get next background byte into A - and (hl) ;; [2] Erase background part that is to be overwritten (Mask step 1) - inc hl ;; [3] HL += 1 => Point HL to Sprite Colour information -sprite_color = .+1 ;; Placeholder for the Sprite Color computed - or #00 ;; [2] Add up background and sprite information in one byte (Mask step 2) - ld (de), a ;; [2] Save modified background + sprite data information into memory - - inc hl ;; [2] Next byte sprite source - inc de ;; [2] Next byte Dest Memory - djnz lineLoop ;; [3] Decrement B (Width) if B != 0 goto lineLoop - - dec c ;; [1] Decrement C (Height) - jr z, end ;; [2/3] If C == O goto end - -startLine = .+1 ;; Placeholder for the Start line adress - ld de, #0000 ;; [3] DE = Start Line - - ld a, d ;; [1] Start of next pixel line normally is 0x0800 bytes away. - add #0x08 ;; [2] so we add it to DE (just by adding 0x08 to D) - ld d, a ;; [1] - and #0x38 ;; [2] We check if we have crossed memory boundary (every 8 pixel lines).. - - jr nz, convertLoop ;; [2/3] .. by checking the 4 bits that identify present memory line. - ;; .... If 0, we have crossed boundaries - -dms_sprite_8bit_boundary_crossed: - ld a, e ;; [1] DE = DE + 0xC050h - add #0x50 ;; [2] -- Relocate DE pointer to the start of the next pixel line: - ld e, a ;; [1] -- DE is moved forward 3 memory banks plus 50 bytes (4000h * 3) - ld a, d ;; [1] -- which effectively is the same as moving it 1 bank backwards and then - adc #0xC0 ;; [2] -- 50 bytes forwards (which is what we want to move it to the next pixel line) - ld d, a ;; [1] -- Calculations are made with 8 bit maths as it is faster than other alternatives here - - jr convertLoop ;; [3] Jump to continue with next pixel line - -end: - ;; Return is included in bindings - diff --git a/examples/medium/colorReplace/src/asm/sprites/colorReplace/M1/cpct_drawSpriteMaskedColorizeM1_asmbindings.s b/examples/medium/colorReplace/src/asm/sprites/colorReplace/M1/cpct_drawSpriteMaskedColorizeM1_asmbindings.s deleted file mode 100644 index b2ed10933..000000000 --- a/examples/medium/colorReplace/src/asm/sprites/colorReplace/M1/cpct_drawSpriteMaskedColorizeM1_asmbindings.s +++ /dev/null @@ -1,36 +0,0 @@ -;;-----------------------------LICENSE NOTICE------------------------------------ -;; This file is part of CPCtelera: An Amstrad CPC Game Engine -;; Copyright (C) 2017 Arnaud Bouche (Arnaud6128) -;; Copyright (C) 2017 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) -;; -;; This program is free software: you can redistribute it and/or modify -;; it under the terms of the GNU Lesser General Public License as published by -;; the Free Software Foundation, either version 3 of the License, or -;; (at your option) any later version. -;; -;; This program is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU Lesser General Public License for more details. -;; -;; You should have received a copy of the GNU Lesser General Public License -;; along with this program. If not, see <http://www.gnu.org/licenses/>. -;;------------------------------------------------------------------------------- -.module cpct_sprites - -.include "../../../macros/cpct_undocumentedOpcodes.s" - -;; -;; ASM bindings for <cpct_drawSpriteMaskedColorizeM1> -;; -cpct_drawSpriteMaskedColorizeM1_asm:: ;; Assembly entry point - - ;; GET Parameters from the stack - ld (dms_restore_ix + 2), ix ;; [6] Save IX to restore it before returning - pop hl ;; [3] HL = Return Address - -.include /cpct_drawSpriteMaskedColorizeM1.asm/ - -dms_restore_ix: - ld ix, #0000 ;; [4] Restore IX before returning - ret ;; [3] Return to caller \ No newline at end of file diff --git a/examples/medium/colorReplace/src/asm/sprites/colorReplace/M1/cpct_drawSpriteMaskedColorizeM1_cbindings.s b/examples/medium/colorReplace/src/asm/sprites/colorReplace/M1/cpct_drawSpriteMaskedColorizeM1_cbindings.s deleted file mode 100644 index aa21c471c..000000000 --- a/examples/medium/colorReplace/src/asm/sprites/colorReplace/M1/cpct_drawSpriteMaskedColorizeM1_cbindings.s +++ /dev/null @@ -1,48 +0,0 @@ -;;-----------------------------LICENSE NOTICE------------------------------------ -;; This file is part of CPCtelera: An Amstrad CPC Game Engine -;; Copyright (C) 2017 Arnaud Bouche (Arnaud6128) -;; Copyright (C) 2017 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) -;; -;; This program is free software: you can redistribute it and/or modify -;; it under the terms of the GNU Lesser General Public License as published by -;; the Free Software Foundation, either version 3 of the License, or -;; (at your option) any later version. -;; -;; This program is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU Lesser General Public License for more details. -;; -;; You should have received a copy of the GNU Lesser General Public License -;; along with this program. If not, see <http://www.gnu.org/licenses/>. -;;------------------------------------------------------------------------------- -.module cpct_sprites - -.include "../../../macros/cpct_undocumentedOpcodes.s" - -;; -;; C bindings for <cpct_drawSpriteMaskedColorizeM1> -;; -;; 33 us, 13 bytes -;; -_cpct_drawSpriteMaskedColorizeM1:: - - ;; GET Parameters from the stack - ld (dms_restore_ix + 2), ix ;; [6] Save IX to restore it before returning - pop hl ;; [3] HL = Return Address - - exx - pop hl ;; [3] HL' = Source address (Sprite) - pop de ;; [3] DE' = Destination Memory - pop bc ;; [5] BC' = (B = Sprite Height, C = Width) - exx - - ex (sp), hl ;; [6] HL = (H = newColor, L = oldColor) - ;; ... and leave Return Address at (SP) as we don't need to restore - ;; ... stack status because callin convention is __z88dk_callee - -.include /cpct_drawSpriteMaskedColorizeM1.asm/ - -dms_restore_ix: - ld ix, #0000 ;; [4] Restore IX before returning - ret ;; [3] Return to caller \ No newline at end of file diff --git a/examples/medium/colorReplace/src/asm/sprites/colorReplace/M1/cpct_spriteColorizeM1.asm b/examples/medium/colorReplace/src/asm/sprites/colorReplace/M1/cpct_spriteColorizeM1.asm deleted file mode 100644 index c29c6d050..000000000 --- a/examples/medium/colorReplace/src/asm/sprites/colorReplace/M1/cpct_spriteColorizeM1.asm +++ /dev/null @@ -1,194 +0,0 @@ -;;-----------------------------LICENSE NOTICE------------------------------------ -;; This file is part of CPCtelera: An Amstrad CPC Game Engine -;; Copyright (C) 2017 Arnaud Bouche (Arnaud6128) -;; Copyright (C) 2017 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) -;; -;; This program is free software: you can redistribute it and/or modify -;; it under the terms of the GNU Lesser General Public License as published by -;; the Free Software Foundation, either version 3 of the License, or -;; (at your option) any later version. -;; -;; This program is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU Lesser General Public License for more details. -;; -;; You should have received a copy of the GNU Lesser General Public License -;; along with this program. If not, see <http://www.gnu.org/licenses/>. -;;------------------------------------------------------------------------------- -.module cpct_sprites - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; -;; Function: cpct_spriteColorizeM1 -;; -;; Replace a color in a sprite and copy to another or the same sprite. -;; -;; C Definition: -;; void <cpct_spriteColorizeM1> (void* *sprite*, void* *spriteColor*, <u8> *width*, <u8> *height*, <u8> *oldColor*, <u8> *newColor*) __z88dk_callee; -;; -;; Input Parameters (6 bytes): -;; (2B HL') sprite - Source Sprite Pointer (array of pixel data) -;; (2B DE') spriteColor - Destination Sprite Pointer (can be also the Source Sprite) (array of pixel data) -;; (1B C' ) height - Sprite Height in bytes (>0) -;; (1B B' ) width - Sprite Width in *bytes* (Beware, *not* in pixels!) -;; (1B L ) oldColor - Color to replace -;; (1B H ) newColor - New color -;; -;; Assembly call (Input parameters on registers): -;; > call cpct_spriteColorizeM1_asm -;; -;; Parameter Restrictions: -;; * *sprite* must be an array containing sprite's pixels data in screen pixel format. -;; Sprite must be rectangular and all bytes in the array must be consecutive pixels, -;; starting from top-left corner and going left-to-right, top-to-bottom down to the -;; bottom-right corner. Total amount of bytes in pixel array should be *width* x *height*. -;; * *spriteColor* must be an array containing the new sprite's pixels data with the new color. -;; * *width* must be the width of the sprite *in bytes*. Always remember that the width must be -;; expressed in bytes and *not* in pixels. -;; The correspondence is mode 1 : 1 byte = 4 pixels -;; * *height* must be the height of the sprite in bytes, and must be greater than 0. -;; There is no practical upper limit to this value. Height of a sprite in -;; bytes and pixels is the same value, as bytes only group consecutive pixels in -;; the horizontal space. -;; * *oldColor* must be the index of color (0 to 3) to replace -;; * *newColor* must be the index of the new color (0 to 3) -;; -;; Known limitations: -;; * This function *will not work from ROM*, as it uses self-modifying code. -;; * This function requires the CPC firmware to be DISABLED. Otherwise, random crashes might happen due to side effects. -;; -;; Destroyed Register values: -;; AF, BC, DE, HL, BC', DE', HL', IX -;; -;; Required memory: -;; C-bindings - 73 bytes -;; ASM-bindings - 60 bytes -;; -;; Time Measures: -;; (start code) -;; Case | microSecs (us) | CPU Cycles -;; ---------------------------------------------------------------- -;; | 29 + (6 + 61W)H | 116 + (24 + 244W)H -;; ---------------------------------------------------------------- -;; W=2,H=16 | 2077 | 8308 -;; W=4,H=32 | 8029 | 32116 -;; ---------------------------------------------------------------- -;; Asm saving | -16 | -64 -;; ---------------------------------------------------------------- -;; (end code) -;; W = *width* in bytes, H = *height* in bytes -;; -;; Credits: -;; Original routine optimized by @Docent and discussed in CPCWiki : -;; http://www.cpcwiki.eu/forum/programming/cpctelera-colorize-sprite/ -;; -;; Thanks to all of them for their help and support. -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -.globl dc_mode1_ct - -;; Macro to convert color to pixel Mode1 : Axxx Axxx -.macro convertPixel ;; From cpct_px2byteM1 - ld bc, #dc_mode1_ct ;; [3] BC points to conversion table (dc_mode1_ct) - - ;; Compute HL += A - add c ;; [1] | C += A - ld c, a ;; [1] | - sub a ;; [1] A = 0 (preserving Carry Flag) - adc b ;; [1] | L += Carry - ld b, a ;; [1] | - - ;; A = *(BC + A) - ld a, (bc) ;; [2] A = Value stored at the table pointed by BC -.endm - - ;; Convert newColor to pixel format (E) - ld a, h ;; [1] A = H new color index - convertPixel ;; [10] | Convert into A - ld e, a ;; [1] | E = A new color : Axxx Axxx - - ;; Convert oldColor to pixel format (D) - ld a, l ;; [1] A = L old color index - convertPixel ;; [10] | Convert into A - ld d, a ;; [1] | D = A old color : Axxx Axxx - - ld c, #0x88 ;; [2] C = First Mask to get pixel A : Axxx Axxx - - exx ;; [1] Switch to Alternate registers - - ld__ixl_c ;; [1] IXL = C (Width) - ld c, b ;; [1] C = B (Height) - -convertLoop: - ld__b_ixl ;; [2] B = IXL (Sprite Width) - -lineLoop: - ld a, (hl) ;; [2] A = (HL) current Byte of sprite - exx ;; [1] Switch to Default registers - - ld l, a ;; [1] L = A current Byte of sprite : ABCD ABCD - and c ;; [2] A |= C (C = 0x88) : Axxx Axxx - - cp d ;; [1] Test if pixel (A) is the old colour to be replaced (D) - jr nz, readPixelA ;; [2/3] If not equal go to next pixel - ld a, e ;; [1] else A = new colour to set (E) - -readPixelA: - ld h, a ;; [1] H = A (current colorized sprite) : Axxx Axxx - - sla l ;; [2] L (current byte of sprite) << 1 : ABCD ABCD -> BCDx BCDx - ld a, l ;; [1] A = L : BCDx BCDx - and c ;; [2] A |= Mask (0x88) : Bxxx Bxxx - - cp d ;; [1] Test if pixel (A) is the old colour to be replaced (D) - jr nz, readPixelB ;; [2/3] If not equal go to next pixel - ld a, e ;; [1] else A = new colour to set (E) - -readPixelB: - rrca ;; [1] A = Axxx Axxx >> 1 : xBxx xBxx - or h ;; [1] A |= H (color byte) : Axxx Axxx - ld h, a ;; [1] H = A : ABxx ABxx - - sla l ;; [2] L ( BCDx BCDx) << 1 : CDxx CDxx - ld a, l ;; [1] A = L : CDxx CDxx - and c ;; [1] A |= C (C = 0x88) : Cxxx Cxxx - - cp d ;; [1] Test if pixel (A) is the old colour to be replaced (D) - jr nz, readPixelC ;; [2/3] If not equal go to next pixel - ld a, e ;; [1] else A = new colour to set (E) - -readPixelC: - rrca ;; [1] A = Axxx Axxx >> 1 : xBxx xBxx - rrca ;; [1] A = xxCx xxCx << 1 : xxCx xxCx - or h ;; [1] A |= H (ABxx ABxx) : ABCx ABCx - ld h, a ;; [1] H = A : ABCx ABCx - - sla l ;; [2] L (BCDx BCDx) << 1 : Dxxx Dxxx - ld a, l ;; [1] A = L : Dxxx Dxxx - and c ;; [1] A |= C (C = 0x88) : Dxxx Dxxx - - cp d ;; [1] Test if pixel (A) is the old colour to be replaced (D) - jr nz, readPixelD ;; [2/3] If not equal go to next pixel - ld a, e ;; [1] else A = new colour to set (E) - -readPixelD: - rrca ;; [1] A = Axxx Axxx >> 1 : xBxx xBxx - rrca ;; [1] A = xBxx xBxx >> 1 : xxCx xxCx - rrca ;; [1] A = xxCx xxxx >> 1 : xxxD xxxD - or h ;; [1] A |= H (ABCx ABCx) : ABCD ABCD - -setByte: - exx ;; [1] Switch to Alternate registers - - ld (de), a ;; [2] Update current sprite byte with pixels - inc hl ;; [2] Next byte sprite source - inc de ;; [2] Next byte sprite colorized - djnz lineLoop ;; [3] Decrement B (Width) if != 0 goto lineLoop - -nextLine: - dec c ;; [1] Decrement C (Height) - jr nz, convertLoop ;; [2/3] If != O goto convertLoop - -end: - ;; Return is included in bindings - diff --git a/examples/medium/colorReplace/src/asm/sprites/colorReplace/M1/cpct_spriteColorizeM1_asmbindings.s b/examples/medium/colorReplace/src/asm/sprites/colorReplace/M1/cpct_spriteColorizeM1_asmbindings.s deleted file mode 100644 index 4deb6e35b..000000000 --- a/examples/medium/colorReplace/src/asm/sprites/colorReplace/M1/cpct_spriteColorizeM1_asmbindings.s +++ /dev/null @@ -1,35 +0,0 @@ -;;-----------------------------LICENSE NOTICE------------------------------------ -;; This file is part of CPCtelera: An Amstrad CPC Game Engine -;; Copyright (C) 2017 Arnaud Bouche (Arnaud6128) -;; Copyright (C) 2017 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) -;; -;; This program is free software: you can redistribute it and/or modify -;; it under the terms of the GNU Lesser General Public License as published by -;; the Free Software Foundation, either version 3 of the License, or -;; (at your option) any later version. -;; -;; This program is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU Lesser General Public License for more details. -;; -;; You should have received a copy of the GNU Lesser General Public License -;; along with this program. If not, see <http://www.gnu.org/licenses/>. -;;------------------------------------------------------------------------------- -.module cpct_sprites - -.include "../../../macros/cpct_undocumentedOpcodes.s" - -;; -;; ASM bindings for <cpct_spriteColorizeM1> -;; -cpct_spriteColorizeM1_asm:: ;; Assembly entry point - - ;; GET Parameters from the stack - ld (dms_restore_ix + 2), ix ;; [6] Save IX to restore it before returning - -.include /cpct_spriteColorizeM1.asm/ - -dms_restore_ix: - ld ix, #0000 ;; [4] Restore IX before returning - ret ;; [3] Return to caller \ No newline at end of file diff --git a/examples/medium/colorReplace/src/asm/sprites/colorReplace/M1/cpct_spriteColorizeM1_cbindings.s b/examples/medium/colorReplace/src/asm/sprites/colorReplace/M1/cpct_spriteColorizeM1_cbindings.s deleted file mode 100644 index 8bca05567..000000000 --- a/examples/medium/colorReplace/src/asm/sprites/colorReplace/M1/cpct_spriteColorizeM1_cbindings.s +++ /dev/null @@ -1,48 +0,0 @@ -;;-----------------------------LICENSE NOTICE------------------------------------ -;; This file is part of CPCtelera: An Amstrad CPC Game Engine -;; Copyright (C) 2017 Arnaud Bouche (Arnaud6128) -;; Copyright (C) 2017 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) -;; -;; This program is free software: you can redistribute it and/or modify -;; it under the terms of the GNU Lesser General Public License as published by -;; the Free Software Foundation, either version 3 of the License, or -;; (at your option) any later version. -;; -;; This program is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU Lesser General Public License for more details. -;; -;; You should have received a copy of the GNU Lesser General Public License -;; along with this program. If not, see <http://www.gnu.org/licenses/>. -;;------------------------------------------------------------------------------- -.module cpct_sprites - -.include "../../../macros/cpct_undocumentedOpcodes.s" - -;; -;; C bindings for <cpct_spriteColorizeM1> -;; -;; 33 us, 13 bytes -;; -_cpct_spriteColorizeM1:: - - ;; GET Parameters from the stack - ld (dms_restore_ix + 2), ix ;; [6] Save IX to restore it before returning - pop hl ;; [3] HL = Return Address - - exx - pop hl ;; [3] HL' = Source address (Sprite) - pop de ;; [3] DE' = Destination Sprite color - pop bc ;; [5] BC' = (B = Sprite Height, C = Width) - exx - - ex (sp), hl ;; [6] HL = (H = newColor, L = oldColor) - ;; ... and leave Return Address at (SP) as we don't need to restore - ;; ... stack status because callin convention is __z88dk_callee - -.include /cpct_spriteColorizeM1.asm/ - -dms_restore_ix: - ld ix, #0000 ;; [4] Restore IX before returning - ret ;; [3] Return to caller \ No newline at end of file diff --git a/examples/medium/colorReplace/src/asm/sprites/colorReplace/M1/cpct_spriteMaskedColorizeM1.asm b/examples/medium/colorReplace/src/asm/sprites/colorReplace/M1/cpct_spriteMaskedColorizeM1.asm deleted file mode 100644 index 82ccbb375..000000000 --- a/examples/medium/colorReplace/src/asm/sprites/colorReplace/M1/cpct_spriteMaskedColorizeM1.asm +++ /dev/null @@ -1,205 +0,0 @@ -;;-----------------------------LICENSE NOTICE------------------------------------ -;; This file is part of CPCtelera: An Amstrad CPC Game Engine -;; Copyright (C) 2017 Arnaud Bouche (Arnaud6128) -;; Copyright (C) 2017 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) -;; -;; This program is free software: you can redistribute it and/or modify -;; it under the terms of the GNU Lesser General Public License as published by -;; the Free Software Foundation, either version 3 of the License, or -;; (at your option) any later version. -;; -;; This program is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU Lesser General Public License for more details. -;; -;; You should have received a copy of the GNU Lesser General Public License -;; along with this program. If not, see <http://www.gnu.org/licenses/>. -;;------------------------------------------------------------------------------- -.module cpct_sprites -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; -;; Function: cpct_spriteMaskedColorizeM1 -;; -;; Replace a color in a Masked sprite and copy to another or the same sprite. -;; -;; C Definition: -;; void <cpct_spriteMaskedColorizeM1> (void* *sprite*, void* *spriteColor*, <u8> *width*, <u8> *height*, <u8> *oldColor*, <u8> *newColor*) __z88dk_callee; -;; -;; Input Parameters (6 bytes): -;; (2B HL') sprite - Source Sprite Pointer (array of pixel data) -;; (2B DE') spriteColor - Destination Sprite Pointer (can be also the Source Sprite) (array of pixel data) -;; (1B C') height - Sprite Height in bytes (>0) -;; (1B B') width - Sprite Width in *bytes* (Beware, *not* in pixels!) -;; (1B L) oldColor - Color to replace -;; (1B H) newColor - New color -;; -;; Assembly call (Input parameters on registers): -;; > call cpct_spriteMaskedColorizeM1_asm -;; -;; Parameter Restrictions: -;; * *sprite* must be an array containing sprite's pixels data in screen pixel format -;; along with mask data. Each mask byte will contain enabled bits as those that should -;; be picked from the background (transparent) and disabled bits for those that will -;; be printed from sprite colour data. Each mask data byte must precede its associated -;; colour data byte. -;; Sprite must be rectangular and all bytes in the array must be consecutive pixels, -;; starting from top-left corner and going left-to-right, top-to-bottom down to the -;; bottom-right corner. Total amount of bytes in pixel array should be -;; 2 x *width* x *height* (mask data doubles array size). -;; * *spriteColor* must be an array containing the new sprite's pixels data with the new color. -;; Total amount of bytes in pixel array should be 2 x *width* x *height* (mask data doubles array size). -;; * *width* must be the width of the sprite *in bytes*. Always remember that the width must be -;; expressed in bytes and *not* in pixels. -;; The correspondence is mode 1 : 1 byte = 4 pixels -;; * *height* must be the height of the sprite in bytes, and must be greater than 0. -;; There is no practical upper limit to this value. Height of a sprite in -;; bytes and pixels is the same value, as bytes only group consecutive pixels in -;; the horizontal space. -;; * *oldColor* must be the index of color (0 to 3) to replace -;; * *newColor* must be the index of the new color (0 to 3) -;; -;; Known limitations: -;; * This function *will not work from ROM*, as it uses self-modifying code. -;; * This function requires the CPC firmware to be DISABLED. Otherwise, random crashes might happen due to side effects. -;; -;; Destroyed Register values: -;; AF, BC, DE, HL, BC', DE', HL', IX -;; -;; Required memory: -;; C-bindings - 110 bytes -;; ASM-bindings - 97 bytes -;; -;; Time Measures: -;; (start code) -;; Case | microSecs (us) | CPU Cycles -;; ---------------------------------------------------------------- -;; | 29 + (6 + 71W)H | 116 + (24 + 284W)H -;; ---------------------------------------------------------------- -;; W=2,H=16 | 2397 | 9588 -;; W=4,H=32 | 9309 | 37236 -;; ---------------------------------------------------------------- -;; Asm saving | -16 | -64 -;; ---------------------------------------------------------------- -;; (end code) -;; W = *width* in bytes, H = *height* in bytes -;; -;; Credits: -;; Original routine optimized by @Docent and discussed in CPCWiki : -;; http://www.cpcwiki.eu/forum/programming/cpctelera-colorize-sprite/ -;; -;; Thanks to all of them for their help and support. -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -.globl dc_mode1_ct - -;; Macro to convert color to pixel Mode1 : Axxx Axxx -.macro convertPixel ;; From cpct_px2byteM1 - ld bc, #dc_mode1_ct ;; [3] HL points to conversion table (dc_mode1_ct) - - ;; Compute HL += A - add c ;; [1] | L += A - ld c, a ;; [1] | - sub a ;; [1] A = 0 (preserving Carry Flag) - adc b ;; [1] | H += Carry - ld b, a ;; [1] | - - ;; A = *(HL + A) - ld a, (bc) ;; [2] A = Value stored at the table pointed by HL -.endm - - ;; Convert newColor to pixel format (E) - ld a, h ;; [1] A = H new color index - convertPixel ;; [10] | Convert into A - ld e, a ;; [1] | E = A new color : Axxx Axxx - - ;; Convert oldColor to pixel format (D) - ld a, l ;; [1] A = L old color index - convertPixel ;; [10] | Convert into A - ld d, a ;; [1] | D = A old color : Axxx Axxx - - ld c, #0x88 ;; [2] C = First Mask to get pixel A : Axxx Axxx - - exx ;; [1] Switch to Alternate registers - - ld__ixl_c ;; [1] IXL = C (Width) - ld c, b ;; [1] C = B (Height) - -convertLoop: - ld__b_ixl ;; [2] B = IXL (Sprite Width) - -lineLoop: - ld a, (hl) ;; [2] A = (HL) current Byte of sprite Mask - ld (de), a ;; [2] (DE) = A Copy of sprite Mask - inc hl ;; [2] Next byte sprite Color source - inc de ;; [2] Next byte sprite Color destination - ld a, (hl) ;; [2] A = (HL) current Byte of sprite Color - - exx ;; [1] Switch to Default registers - - ld l, a ;; [1] L = A current Byte of sprite : ABCD ABCD - - and c ;; [2] A |= C (C = 0x88) : Axxx Axxx - - cp d ;; [1] Test if pixel (A) is the old colour to be replaced (D) - jr nz, readPixelA ;; [2/3] If not equal go to next pixel - ld a, e ;; [1] else A = new colour to set (E) - -readPixelA: - ld h, a ;; [1] H = A (current colorized sprite) : Axxx Axxx - - sla l ;; [2] L (current byte of sprite) << 1 : ABCD ABCD -> BCDx BCDx - ld a, l ;; [1] A = L : BCDx BCDx - and c ;; [2] A |= Mask (0x88) : Bxxx Bxxx - - cp d ;; [1] Test if pixel (A) is the old colour to be replaced (D) - jr nz, readPixelB ;; [2/3] If not equal go to next pixel - ld a, e ;; [1] else A = new colour to set (E) - -readPixelB: - rrca ;; [1] A = Axxx Axxx >> 1 : xBxx xBxx - or h ;; [1] A |= H (color byte) : Axxx Axxx - ld h, a ;; [1] H = A : ABxx ABxx - - sla l ;; [2] L ( BCDx BCDx) << 1 : CDxx CDxx - ld a, l ;; [1] A = L : CDxx CDxx - and c ;; [1] A |= C (C = 0x88) : Cxxx Cxxx - - cp d ;; [1] Test if pixel (A) is the old colour to be replaced (D) - jr nz, readPixelC ;; [2/3] If not equal go to next pixel - ld a, e ;; [1] else A = new colour to set (E) - -readPixelC: - rrca ;; [1] A = Axxx Axxx >> 1 : xBxx xBxx - rrca ;; [1] A = xxCx xxCx << 1 : xxCx xxCx - or h ;; [1] A |= H (ABxx ABxx) : ABCx ABCx - ld h, a ;; [1] H = A : ABCx ABCx - - sla l ;; [2] L (BCDx BCDx) << 1 : Dxxx Dxxx - ld a, l ;; [1] A = L : Dxxx Dxxx - and c ;; [1] A |= C (C = 0x88) : Dxxx Dxxx - - cp d ;; [1] Test if pixel (A) is the old colour to be replaced (D) - jr nz, readPixelD ;; [2/3] If not equal go to next pixel - ld a, e ;; [1] else A = new colour to set (E) - -readPixelD: - rrca ;; [1] A = Axxx Axxx >> 1 : xBxx xBxx - rrca ;; [1] A = xBxx xBxx >> 1 : xxCx xxCx - rrca ;; [1] A = xxCx xxxx >> 1 : xxxD xxxD - or h ;; [1] A |= H (ABCx ABCx) : ABCD ABCD - -setByte: - exx ;; [1] Switch to Alternate registers - - ld (de), a ;; [2] Update current sprite byte with pixels - inc hl ;; [2] Next byte sprite source - inc de ;; [2] Next byte sprite colorized - djnz lineLoop ;; [3] Decrement B (Width) if != 0 goto lineLoop - -nextLine: - dec c ;; [1] Decrement C (Height) - jr nz, convertLoop ;; [2/3] If != O goto convertLoop - -end: - ;; Return is included in bindings \ No newline at end of file diff --git a/examples/medium/colorReplace/src/asm/sprites/colorReplace/M1/cpct_spriteMaskedColorizeM1_asmbindings.s b/examples/medium/colorReplace/src/asm/sprites/colorReplace/M1/cpct_spriteMaskedColorizeM1_asmbindings.s deleted file mode 100644 index cc7d49e23..000000000 --- a/examples/medium/colorReplace/src/asm/sprites/colorReplace/M1/cpct_spriteMaskedColorizeM1_asmbindings.s +++ /dev/null @@ -1,36 +0,0 @@ -;;-----------------------------LICENSE NOTICE------------------------------------ -;; This file is part of CPCtelera: An Amstrad CPC Game Engine -;; Copyright (C) 2017 Arnaud Bouche (Arnaud6128) -;; Copyright (C) 2017 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) -;; -;; This program is free software: you can redistribute it and/or modify -;; it under the terms of the GNU Lesser General Public License as published by -;; the Free Software Foundation, either version 3 of the License, or -;; (at your option) any later version. -;; -;; This program is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU Lesser General Public License for more details. -;; -;; You should have received a copy of the GNU Lesser General Public License -;; along with this program. If not, see <http://www.gnu.org/licenses/>. -;;------------------------------------------------------------------------------- -.module cpct_sprites - -.include "../../../macros/cpct_undocumentedOpcodes.s" - -;; -;; ASM bindings for <cpct_spriteMaskedColorizeM1> -;; -cpct_spriteMaskedColorizeM1_asm:: ;; Assembly entry point - - ;; GET Parameters from the stack - ld (dms_restore_ix + 2), ix ;; [6] Save IX to restore it before returning - pop hl ;; [3] HL = Return Address - -.include /cpct_spriteMaskedColorizeM1.asm/ - -dms_restore_ix: - ld ix, #0000 ;; [4] Restore IX before returning - ret ;; [3] Return to caller \ No newline at end of file diff --git a/examples/medium/colorReplace/src/asm/sprites/colorReplace/M1/cpct_spriteMaskedColorizeM1_cbindings.s b/examples/medium/colorReplace/src/asm/sprites/colorReplace/M1/cpct_spriteMaskedColorizeM1_cbindings.s deleted file mode 100644 index 3e4784f8a..000000000 --- a/examples/medium/colorReplace/src/asm/sprites/colorReplace/M1/cpct_spriteMaskedColorizeM1_cbindings.s +++ /dev/null @@ -1,48 +0,0 @@ -;;-----------------------------LICENSE NOTICE------------------------------------ -;; This file is part of CPCtelera: An Amstrad CPC Game Engine -;; Copyright (C) 2017 Arnaud Bouche (Arnaud6128) -;; Copyright (C) 2017 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) -;; -;; This program is free software: you can redistribute it and/or modify -;; it under the terms of the GNU Lesser General Public License as published by -;; the Free Software Foundation, either version 3 of the License, or -;; (at your option) any later version. -;; -;; This program is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU Lesser General Public License for more details. -;; -;; You should have received a copy of the GNU Lesser General Public License -;; along with this program. If not, see <http://www.gnu.org/licenses/>. -;;------------------------------------------------------------------------------- -.module cpct_sprites - -.include "../../../macros/cpct_undocumentedOpcodes.s" - -;; -;; C bindings for <cpct_spriteMaskedColorizeM1> -;; -;; 33 us, 13 bytes -;; -_cpct_spriteMaskedColorizeM1:: - - ;; GET Parameters from the stack - ld (dms_restore_ix + 2), ix ;; [6] Save IX to restore it before returning - pop hl ;; [3] HL = Return Address - - exx - pop hl ;; [3] HL' = Source address (Sprite) - pop de ;; [3] DE' = Destination Sprite color - pop bc ;; [5] BC' = (B = Sprite Height, C = Width) - exx - - ex (sp), hl ;; [6] HL = (H = newColor, L = oldColor) - ;; ... and leave Return Address at (SP) as we don't need to restore - ;; ... stack status because callin convention is __z88dk_callee - -.include /cpct_spriteMaskedColorizeM1.asm/ - -dms_restore_ix: - ld ix, #0000 ;; [4] Restore IX before returning - ret ;; [3] Return to caller \ No newline at end of file diff --git a/examples/medium/colorReplace/src/sprites/baloon.c b/examples/medium/colorReplace/src/sprites/baloon.c deleted file mode 100644 index 79910f7bc..000000000 --- a/examples/medium/colorReplace/src/sprites/baloon.c +++ /dev/null @@ -1,43 +0,0 @@ -#include "baloon.h" -// Data created with Img2CPC - (c) Retroworks - 2007-2015 -// Palette uses hardware values. -const u8 g_palette[16] = { 0x40, 0x44, 0x55, 0x5c, 0x4c, 0x58, 0x5d, 0x4d, 0x4f, 0x56, 0x52, 0x4e, 0x4a, 0x54, 0x57, 0x4b }; - -// Tile g_baloon: 20x34 pixels, 10x34 bytes. -const u8 g_baloon[10 * 34] = { - 0x00, 0x00, 0x00, 0x51, 0xf3, 0xf3, 0xa2, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x51, 0xa6, 0x0c, 0x0c, 0x59, 0xa2, 0x00, 0x00, - 0x00, 0x00, 0xa6, 0xae, 0x0c, 0x0c, 0x0c, 0x59, 0x00, 0x00, - 0x00, 0x51, 0xae, 0x0c, 0xae, 0x0c, 0x0c, 0x0c, 0xa2, 0x00, - 0x00, 0xa6, 0x0c, 0xae, 0x0c, 0x0c, 0x0c, 0x0c, 0x59, 0x00, - 0x51, 0x5d, 0x5d, 0xff, 0x5d, 0x0c, 0x0c, 0x0c, 0x0c, 0xa2, - 0x51, 0x0c, 0x0c, 0xae, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0xa2, - 0x51, 0x0c, 0xae, 0x0c, 0xae, 0x0c, 0x0c, 0x0c, 0x0c, 0xa2, - 0xa6, 0x0c, 0x0c, 0xae, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x59, - 0xa6, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x59, - 0xa6, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x59, - 0xa6, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x59, - 0xa6, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x59, - 0xa6, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x59, - 0xa6, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x59, - 0xa6, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x59, - 0xa6, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x59, - 0xa6, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x59, - 0x51, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0xa2, - 0x51, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0xa2, - 0x51, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0xa2, - 0x00, 0xa6, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x59, 0x00, - 0x00, 0xa6, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x59, 0x00, - 0x00, 0x51, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0xa2, 0x00, - 0x00, 0x00, 0xa6, 0x0c, 0x0c, 0x0c, 0x0c, 0x59, 0x00, 0x00, - 0x00, 0x00, 0xe2, 0x0c, 0x0c, 0x0c, 0x0c, 0xd1, 0x00, 0x00, - 0x00, 0x00, 0x51, 0xc0, 0x0c, 0x0c, 0xc0, 0xa2, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xe2, 0x84, 0x48, 0xd1, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x51, 0xc0, 0xc0, 0xa2, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xe2, 0xd1, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xe7, 0xdb, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x51, 0xc0, 0xc0, 0xa2, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xe2, 0xe2, 0xd1, 0xd1, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x51, 0x51, 0xa2, 0xa2, 0x00, 0x00, 0x00 -}; - diff --git a/examples/medium/colorReplace/src/sprites/baloon.h b/examples/medium/colorReplace/src/sprites/baloon.h deleted file mode 100644 index e9fc3e64f..000000000 --- a/examples/medium/colorReplace/src/sprites/baloon.h +++ /dev/null @@ -1,12 +0,0 @@ -// Data created with Img2CPC - (c) Retroworks - 2007-2015 -#ifndef _IMG_BALOON_H_ -#define _IMG_BALOON_H_ - -#include <types.h> -extern const u8 g_palette[16]; - -#define G_BALOON_W 10 -#define G_BALOON_H 34 -extern const u8 g_baloon[10 * 34]; - -#endif diff --git a/examples/medium/colorReplace/src/sprites/circle_trans.c b/examples/medium/colorReplace/src/sprites/circle_trans.c deleted file mode 100644 index 30b2a8876..000000000 --- a/examples/medium/colorReplace/src/sprites/circle_trans.c +++ /dev/null @@ -1,12 +0,0 @@ -#include "circle_trans.h" -// Data created with Img2CPC - (c) Retroworks - 2007-2015 -// Tile g_circle_trans: 4x6 pixels, 2x6 bytes. -const u8 g_circle_trans[2 * 2 * 6] = { - 0xaa, 0x55, 0xff, 0x00, - 0x00, 0xff, 0x55, 0xaa, - 0x00, 0xff, 0x55, 0xaa, - 0x00, 0xff, 0x55, 0xaa, - 0x00, 0xff, 0x55, 0xaa, - 0xaa, 0x55, 0xff, 0x00 -}; - diff --git a/examples/medium/colorReplace/src/sprites/circle_trans.h b/examples/medium/colorReplace/src/sprites/circle_trans.h deleted file mode 100644 index a3dbf1367..000000000 --- a/examples/medium/colorReplace/src/sprites/circle_trans.h +++ /dev/null @@ -1,10 +0,0 @@ -// Data created with Img2CPC - (c) Retroworks - 2007-2015 -#ifndef _IMG_CIRCLE_TRANS_H_ -#define _IMG_CIRCLE_TRANS_H_ - -#include <types.h> -#define G_CIRCLE_TRANS_W 2 -#define G_CIRCLE_TRANS_H 6 -extern const u8 g_circle_trans[2 * 2 * 6]; - -#endif diff --git a/examples/medium/colorReplace/src/sprites/cloud.c b/examples/medium/colorReplace/src/sprites/cloud.c deleted file mode 100644 index 6400be15d..000000000 --- a/examples/medium/colorReplace/src/sprites/cloud.c +++ /dev/null @@ -1,60 +0,0 @@ -#include "cloud.h" -// Data created with Img2CPC - (c) Retroworks - 2007-2015 -// Tile g_cloud: 62x54 pixels, 31x54 bytes. -const u8 g_cloud[31 * 54] = { - 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x7f, 0xbf, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, - 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0xff, 0xff, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, - 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0xff, 0xff, 0xff, 0xbf, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, - 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, - 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, - 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, - 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, - 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, - 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, - 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, - 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, - 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, - 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, - 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, - 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, - 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, - 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, - 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, - 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, - 0x3f, 0x3f, 0x3f, 0x3f, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x7f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, - 0x3f, 0x3f, 0x3f, 0x3f, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, - 0x3f, 0x3f, 0x3f, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, - 0x3f, 0x3f, 0x3f, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, - 0x3f, 0x3f, 0x3f, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0x3f, 0x3f, 0x3f, 0x3f, - 0x3f, 0x3f, 0x3f, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x3f, - 0x3f, 0x3f, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0x3f, - 0x3f, 0x3f, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0x3f, - 0x3f, 0x3f, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, - 0x3f, 0x3f, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, - 0x3f, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, - 0x3f, 0x3f, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, - 0x3f, 0x3f, 0xff, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0xbf, - 0x3f, 0x3f, 0x7f, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, - 0x3f, 0x3f, 0xbf, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0xff, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, - 0x3f, 0x3f, 0x7f, 0x7f, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, - 0x3f, 0x3f, 0x3f, 0xbf, 0xbf, 0xbf, 0xff, 0xff, 0xff, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0xbf, - 0x3f, 0x3f, 0x3f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0xff, 0xff, 0xff, 0x7f, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x7f, 0xff, 0xff, 0x7f, - 0x3f, 0x3f, 0x3f, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xff, 0xbf, 0xff, 0xff, 0xff, 0xbf, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0xbf, 0xff, 0xff, 0xbf, 0xbf, - 0x3f, 0x3f, 0x3f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x7f, 0xff, 0x7f, 0x7f, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, - 0x3f, 0x3f, 0x3f, 0x3f, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xff, 0xff, 0xbf, 0xbf, 0xff, 0xff, 0xbf, 0xbf, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0xff, 0xbf, 0xbf, 0xbf, 0xbf, - 0x3f, 0x3f, 0x3f, 0x3f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0xff, 0xff, 0x7f, 0x7f, 0xff, 0xff, 0x7f, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xff, 0x7f, 0x7f, 0x3f, 0x3f, - 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xff, 0xff, 0xbf, 0xbf, 0xbf, 0xff, 0xbf, 0xff, 0xbf, 0xff, 0xbf, 0xbf, 0xff, 0xbf, 0xbf, 0xbf, 0x3f, - 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0xff, 0xff, 0x7f, 0x7f, 0xff, 0xff, 0xff, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0xff, 0x7f, 0x7f, 0x3f, 0x3f, - 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0xbf, 0x3f, 0x3f, 0x3f, 0x3f, 0xbf, 0xbf, 0xbf, 0xbf, 0xff, 0xbf, 0xbf, 0xff, 0xbf, 0xbf, 0xff, 0xbf, 0xbf, 0xbf, 0xff, 0xbf, 0xbf, 0xbf, 0xbf, 0x3f, - 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x3f, 0x3f, - 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0xbf, 0xbf, 0xbf, 0x3f, 0x3f, 0xbf, 0xbf, 0xff, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0x3f, 0x3f, 0x3f, - 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x7f, 0x3f, 0x3f, 0x3f, 0x7f, 0x7f, 0xff, 0xff, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x3f, 0x3f, 0x3f, 0x3f, - 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0xbf, 0xff, 0xbf, 0xff, 0xff, 0xbf, 0xbf, 0xbf, 0xbf, 0x3f, 0x3f, 0x3f, 0x3f, - 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x7f, 0x7f, 0xff, 0xff, 0x7f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, - 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, - 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, - 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0xbf, 0xbf, 0xbf, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, - 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x7f, 0x7f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, - 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0xbf, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f -}; - diff --git a/examples/medium/colorReplace/src/sprites/cloud.h b/examples/medium/colorReplace/src/sprites/cloud.h deleted file mode 100644 index d6fc74738..000000000 --- a/examples/medium/colorReplace/src/sprites/cloud.h +++ /dev/null @@ -1,10 +0,0 @@ -// Data created with Img2CPC - (c) Retroworks - 2007-2015 -#ifndef _IMG_CLOUD_H_ -#define _IMG_CLOUD_H_ - -#include <types.h> -#define G_CLOUD_W 31 -#define G_CLOUD_H 54 -extern const u8 g_cloud[31 * 54]; - -#endif diff --git a/examples/medium/colorReplace/src/sprites/roof.c b/examples/medium/colorReplace/src/sprites/roof.c deleted file mode 100644 index aa3a87955..000000000 --- a/examples/medium/colorReplace/src/sprites/roof.c +++ /dev/null @@ -1,26 +0,0 @@ -#include "roof.h" -// Data created with Img2CPC - (c) Retroworks - 2007-2015 -// Tile g_roof: 80x20 pixels, 40x20 bytes. -const u8 g_roof[40 * 20] = { - 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xd9, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xd9, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xd9, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xd9, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xd9, - 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x71, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x71, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x71, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x71, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x71, - 0x30, 0x64, 0x64, 0x64, 0x64, 0xcf, 0xcc, 0xd9, 0x30, 0x64, 0x64, 0x64, 0x64, 0xcf, 0xcc, 0xd9, 0x30, 0x64, 0x64, 0x64, 0x64, 0xcf, 0xcc, 0xd9, 0x30, 0x64, 0x64, 0x64, 0x64, 0xcf, 0xcc, 0xd9, 0x30, 0x64, 0x64, 0x64, 0x64, 0xcf, 0xcc, 0xd9, - 0xce, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xd9, 0xce, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xd9, 0xce, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xd9, 0xce, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xd9, 0xce, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xd9, - 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xd9, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xd9, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xd9, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xd9, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xd9, - 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, - 0xcc, 0xcc, 0xe6, 0xe6, 0xe6, 0x98, 0xe6, 0xcc, 0xe6, 0xcc, 0xe6, 0xcc, 0xe6, 0xcc, 0xe6, 0xcc, 0xcc, 0xcc, 0xe6, 0xe6, 0xe6, 0xcc, 0xe6, 0xcc, 0xe6, 0xcc, 0xe6, 0xcc, 0xe6, 0xcc, 0xe6, 0xcc, 0xcc, 0xcc, 0xe6, 0xe6, 0xe6, 0xcc, 0xe6, 0x98, - 0xb2, 0x30, 0xf3, 0xb2, 0xb2, 0x30, 0xb2, 0x71, 0xb2, 0x30, 0xf3, 0x30, 0xb2, 0x30, 0xb2, 0x71, 0xb2, 0x30, 0xf3, 0xb2, 0xb2, 0x30, 0xb2, 0x71, 0xb2, 0x30, 0xf3, 0x30, 0xb2, 0x30, 0xb2, 0x71, 0xb2, 0x30, 0xf3, 0xb2, 0xb2, 0x30, 0xb2, 0x71, - 0xb2, 0x30, 0xf3, 0x71, 0xb2, 0x30, 0xf3, 0xf3, 0xb2, 0x30, 0xf3, 0x71, 0xb2, 0x30, 0xf3, 0xf3, 0xb2, 0x30, 0xf3, 0x71, 0xb2, 0x30, 0xf3, 0xf3, 0xb2, 0x30, 0xf3, 0x71, 0xb2, 0x30, 0xf3, 0xf3, 0xb2, 0x30, 0xf3, 0xd9, 0xb2, 0x30, 0xf3, 0xf3, - 0xf3, 0xf3, 0xb2, 0x30, 0xf3, 0xf3, 0xe6, 0xcc, 0xf3, 0xf3, 0xe6, 0xcc, 0xf3, 0xf3, 0xe6, 0xcc, 0xf3, 0xf3, 0xb2, 0x30, 0xf3, 0xf3, 0xe6, 0xcc, 0xf3, 0xf3, 0xe6, 0xcc, 0xf3, 0xf3, 0xe6, 0xcc, 0xf3, 0xf3, 0xe6, 0x64, 0xf3, 0xf3, 0xe6, 0xcc, - 0xe6, 0xcc, 0xb2, 0x30, 0xe6, 0xcc, 0xb2, 0x30, 0xe6, 0xcc, 0xb2, 0x30, 0xe6, 0xcc, 0xb2, 0x30, 0xe6, 0xcc, 0xb2, 0x30, 0xe6, 0xcc, 0xb2, 0x30, 0xe6, 0xcc, 0xb2, 0x30, 0xe6, 0xcc, 0xb2, 0x30, 0xe6, 0xcc, 0xb2, 0x30, 0xe6, 0xcc, 0xb2, 0x30, - 0x65, 0x30, 0xb2, 0x64, 0xb2, 0x64, 0x30, 0x30, 0xb2, 0x30, 0xb2, 0x30, 0xe6, 0x30, 0x30, 0x30, 0xb2, 0x30, 0xe6, 0x30, 0xb2, 0x30, 0x98, 0x98, 0xb2, 0x30, 0xb2, 0x30, 0xb2, 0x30, 0x64, 0x30, 0xb2, 0x30, 0xb2, 0x30, 0xb2, 0x30, 0xb2, 0x64, - 0x65, 0x30, 0xb2, 0x98, 0xb2, 0x30, 0x30, 0x64, 0xb2, 0x30, 0xb2, 0x30, 0xb2, 0x30, 0x65, 0x30, 0xb2, 0x30, 0xb2, 0x64, 0xb2, 0x30, 0xcc, 0x30, 0xb2, 0x30, 0xb2, 0x98, 0xb2, 0x30, 0xcd, 0x30, 0xb2, 0x30, 0xe6, 0x64, 0xb2, 0x30, 0xe6, 0x30, - 0x65, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x64, 0xe7, 0x30, 0x30, 0x30, 0x64, 0x30, 0x65, 0x30, 0xe7, 0x30, 0x98, 0x30, 0x98, 0x30, 0x30, 0x30, 0xe7, 0x30, 0xcc, 0x30, 0x98, 0x30, 0x65, 0x30, 0xe7, 0x30, 0x98, 0x98, 0x30, 0x30, 0xb2, 0x98, - 0x65, 0xcf, 0x30, 0xcf, 0xe7, 0x30, 0x65, 0x30, 0xe7, 0xcf, 0x30, 0xcf, 0xe7, 0x30, 0x65, 0x9a, 0xe7, 0xcf, 0x30, 0xcf, 0xe7, 0x30, 0x65, 0x30, 0xe7, 0xcf, 0x30, 0xcf, 0xe7, 0x30, 0x65, 0x9a, 0xe7, 0xcf, 0x30, 0xcf, 0xe7, 0x64, 0x65, 0x30, - 0xe7, 0xcf, 0xe7, 0x9a, 0xe7, 0x9a, 0xb2, 0xdb, 0xe7, 0xcf, 0xe7, 0x9a, 0xe7, 0x9a, 0xb2, 0xdb, 0xe7, 0xcf, 0xe7, 0x9a, 0xe7, 0x9a, 0xb2, 0xdb, 0xe7, 0xcf, 0xe7, 0x9a, 0xe7, 0x9a, 0xb2, 0xdb, 0xe7, 0xcf, 0xe7, 0x9a, 0xe7, 0x9a, 0xb2, 0xdb, - 0xf3, 0x9a, 0xf3, 0xf3, 0xf3, 0x9a, 0xf3, 0xf3, 0xf3, 0x9a, 0xf3, 0xf3, 0xf3, 0x9a, 0xf3, 0xf3, 0xf3, 0x9a, 0xf3, 0xf3, 0xf3, 0x9a, 0xf3, 0xf3, 0xf3, 0x9a, 0xf3, 0xf3, 0xf3, 0x9a, 0xf3, 0xf3, 0xf3, 0x9a, 0xf3, 0xf3, 0xf3, 0x9a, 0xf3, 0xf3, - 0xf3, 0xf3, 0xb2, 0x30, 0xf3, 0xf3, 0xe6, 0xcc, 0xf3, 0xf3, 0xe6, 0xcc, 0xd9, 0xf3, 0xe6, 0xcc, 0xf3, 0xf3, 0xe6, 0xcc, 0xf3, 0xf3, 0xe6, 0xcc, 0xf3, 0xf3, 0xe6, 0xcc, 0xf3, 0xf3, 0xe6, 0xcc, 0xf3, 0xf3, 0xe6, 0xcc, 0xf3, 0xf3, 0xe6, 0xcc, - 0xe7, 0x30, 0xb2, 0x30, 0xb2, 0xcc, 0xb2, 0x30, 0xb2, 0x30, 0xb2, 0x30, 0xe6, 0xcc, 0xb2, 0x30, 0xe6, 0xcc, 0xb2, 0x30, 0xe6, 0xcc, 0xb2, 0x30, 0xe6, 0xcc, 0xb2, 0x30, 0xe6, 0xcc, 0xb2, 0x30, 0xe6, 0x98, 0xb2, 0x30, 0xe6, 0xcc, 0xb2, 0x30, - 0x65, 0x30, 0xe7, 0x30, 0xb2, 0x30, 0xb2, 0x30, 0x30, 0x30, 0xe7, 0x30, 0xb2, 0x30, 0xb2, 0x30, 0x30, 0x30, 0xe7, 0x30, 0xb2, 0x30, 0xb2, 0x30, 0x30, 0x30, 0xe7, 0x30, 0xb2, 0x30, 0xb2, 0x30, 0x30, 0x30, 0xe7, 0x30, 0xb2, 0x30, 0xb2, 0x30 -}; - diff --git a/examples/medium/colorReplace/src/sprites/roof.h b/examples/medium/colorReplace/src/sprites/roof.h deleted file mode 100644 index f6d1e5a09..000000000 --- a/examples/medium/colorReplace/src/sprites/roof.h +++ /dev/null @@ -1,10 +0,0 @@ -// Data created with Img2CPC - (c) Retroworks - 2007-2015 -#ifndef _IMG_ROOF_H_ -#define _IMG_ROOF_H_ - -#include <types.h> -#define G_ROOF_W 40 -#define G_ROOF_H 20 -extern const u8 g_roof[40 * 20]; - -#endif diff --git a/examples/medium/colorReplace/src/sprites/sprites_gen.txt b/examples/medium/colorReplace/src/sprites/sprites_gen.txt new file mode 100644 index 000000000..e69de29bb diff --git a/examples/medium/colorReplace/src/sprites/square.c b/examples/medium/colorReplace/src/sprites/square.c deleted file mode 100644 index acdfaea36..000000000 --- a/examples/medium/colorReplace/src/sprites/square.c +++ /dev/null @@ -1,12 +0,0 @@ -#include "square.h" -// Data created with Img2CPC - (c) Retroworks - 2007-2015 -// Tile g_square: 4x6 pixels, 2x6 bytes. -const u8 g_square[2 * 6] = { - 0xff, 0xaa, - 0xff, 0xaa, - 0xff, 0xaa, - 0xff, 0xaa, - 0xff, 0xaa, - 0xff, 0xaa -}; - diff --git a/examples/medium/colorReplace/src/sprites/square.h b/examples/medium/colorReplace/src/sprites/square.h deleted file mode 100644 index 693116632..000000000 --- a/examples/medium/colorReplace/src/sprites/square.h +++ /dev/null @@ -1,10 +0,0 @@ -// Data created with Img2CPC - (c) Retroworks - 2007-2015 -#ifndef _IMG_SQUARE_H_ -#define _IMG_SQUARE_H_ - -#include <types.h> -#define G_SQUARE_W 2 -#define G_SQUARE_H 6 -extern const u8 g_square[2 * 6]; - -#endif diff --git a/examples/medium/colorReplace/src/sprites/star_trans.c b/examples/medium/colorReplace/src/sprites/star_trans.c deleted file mode 100644 index b11648f2f..000000000 --- a/examples/medium/colorReplace/src/sprites/star_trans.c +++ /dev/null @@ -1,12 +0,0 @@ -#include "star_trans.h" -// Data created with Img2CPC - (c) Retroworks - 2007-2015 -// Tile g_star_trans: 4x6 pixels, 2x6 bytes. -const u8 g_star_trans[2 * 2 * 6] = { - 0xaa, 0x55, 0xff, 0x00, - 0xaa, 0x55, 0xff, 0x00, - 0x00, 0xff, 0x55, 0xaa, - 0x00, 0xff, 0x55, 0xaa, - 0xaa, 0x55, 0xff, 0x00, - 0xaa, 0x55, 0xff, 0x00 -}; - diff --git a/examples/medium/colorReplace/src/sprites/star_trans.h b/examples/medium/colorReplace/src/sprites/star_trans.h deleted file mode 100644 index afdd9f47f..000000000 --- a/examples/medium/colorReplace/src/sprites/star_trans.h +++ /dev/null @@ -1,10 +0,0 @@ -// Data created with Img2CPC - (c) Retroworks - 2007-2015 -#ifndef _IMG_STAR_TRANS_H_ -#define _IMG_STAR_TRANS_H_ - -#include <types.h> -#define G_STAR_TRANS_W 2 -#define G_STAR_TRANS_H 6 -extern const u8 g_star_trans[2 * 2 * 6]; - -#endif From 8effe52360071c536338f8c6f8f4f2d24b9963be Mon Sep 17 00:00:00 2001 From: Arnaud <arnaud_bouche@hotmail.com> Date: Sat, 20 Jan 2018 13:12:38 +0100 Subject: [PATCH 10/31] Add extern keyword to functions in colorreplace header --- .../src/sprites/colorReplace/colorReplace.h | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/cpctelera/src/sprites/colorReplace/colorReplace.h b/cpctelera/src/sprites/colorReplace/colorReplace.h index 598498fdc..d5675f624 100644 --- a/cpctelera/src/sprites/colorReplace/colorReplace.h +++ b/cpctelera/src/sprites/colorReplace/colorReplace.h @@ -29,21 +29,21 @@ #define CPCT_COLORREPLACE_H // Functions to replace a color in sprite M0 -void cpct_spriteColorizeM0(u8* sprite, u8* spriteColor, u8 width, u8 height, u8 oldColor, u8 newColor) __z88dk_callee; -void cpct_spriteMaskedColorizeM0(u8* sprite, u8* spriteColor, u8 width, u8 height, u8 oldColor, u8 newColor) __z88dk_callee; +extern void cpct_spriteColorizeM0(u8* sprite, u8* spriteColor, u8 width, u8 height, u8 oldColor, u8 newColor) __z88dk_callee; +extern void cpct_spriteMaskedColorizeM0(u8* sprite, u8* spriteColor, u8 width, u8 height, u8 oldColor, u8 newColor) __z88dk_callee; // Functions to draw a sprite M0 with a color replaced -void cpct_drawSpriteColorizeM0(u8* sprite, u8* destMem, u8 width, u8 height, u8 oldColor, u8 newColor) __z88dk_callee; -void cpct_drawSpriteMaskedColorizeM0(u8* sprite, u8* destMem, u8 width, u8 height, u8 oldColor, u8 newColor) __z88dk_callee; -void cpct_drawSpriteMaskedAlignedColorizeM0(u8* sprite, u8* destMem, u8 width, u8 height, u8 oldColor, u8 newColor, const u8* maskTable) __z88dk_callee; +extern void cpct_drawSpriteColorizeM0(u8* sprite, u8* destMem, u8 width, u8 height, u8 oldColor, u8 newColor) __z88dk_callee; +extern void cpct_drawSpriteMaskedColorizeM0(u8* sprite, u8* destMem, u8 width, u8 height, u8 oldColor, u8 newColor) __z88dk_callee; +extern void cpct_drawSpriteMaskedAlignedColorizeM0(u8* sprite, u8* destMem, u8 width, u8 height, u8 oldColor, u8 newColor, const u8* maskTable) __z88dk_callee; // Functions to replace a color in sprite M1 -void cpct_spriteColorizeM1(u8* sprite, u8* spriteColor, u8 width, u8 height, u8 oldColor, u8 newColor) __z88dk_callee; -void cpct_spriteMaskedColorizeM1(u8* sprite, u8* spriteColor, u8 width, u8 height, u8 oldColor, u8 newColor) __z88dk_callee; +extern void cpct_spriteColorizeM1(u8* sprite, u8* spriteColor, u8 width, u8 height, u8 oldColor, u8 newColor) __z88dk_callee; +extern void cpct_spriteMaskedColorizeM1(u8* sprite, u8* spriteColor, u8 width, u8 height, u8 oldColor, u8 newColor) __z88dk_callee; // Functions to draw a sprite M1 with a color replaced -void cpct_drawSpriteColorizeM1(u8* sprite, u8* destMem, u8 width, u8 height, u8 oldColor, u8 newColor) __z88dk_callee; -void cpct_drawSpriteMaskedColorizeM1(u8* sprite, u8* destMem, u8 width, u8 height, u8 oldColor, u8 newColor) __z88dk_callee; -void cpct_drawSpriteMaskedAlignedColorizeM1(u8* sprite, u8* destMem, u8 width, u8 height, u8 oldColor, u8 newColor, const u8* maskTable) __z88dk_callee; +extern void cpct_drawSpriteColorizeM1(u8* sprite, u8* destMem, u8 width, u8 height, u8 oldColor, u8 newColor) __z88dk_callee; +extern void cpct_drawSpriteMaskedColorizeM1(u8* sprite, u8* destMem, u8 width, u8 height, u8 oldColor, u8 newColor) __z88dk_callee; +extern void cpct_drawSpriteMaskedAlignedColorizeM1(u8* sprite, u8* destMem, u8 width, u8 height, u8 oldColor, u8 newColor, const u8* maskTable) __z88dk_callee; #endif \ No newline at end of file From 242164f7a33638ebeb6e8bf93d669d59ff96d781 Mon Sep 17 00:00:00 2001 From: Arnaud <arnaud_bouche@hotmail.com> Date: Sat, 20 Jan 2018 13:23:44 +0100 Subject: [PATCH 11/31] Add sprites generation directory --- examples/medium/screenCapture/src/sprites/sprites_gen.txt | 1 + 1 file changed, 1 insertion(+) create mode 100644 examples/medium/screenCapture/src/sprites/sprites_gen.txt diff --git a/examples/medium/screenCapture/src/sprites/sprites_gen.txt b/examples/medium/screenCapture/src/sprites/sprites_gen.txt new file mode 100644 index 000000000..5f563f4d3 --- /dev/null +++ b/examples/medium/screenCapture/src/sprites/sprites_gen.txt @@ -0,0 +1 @@ +Sprites generation directory \ No newline at end of file From 35a944a654b19ce1949b0f72461876cf00a6bf17 Mon Sep 17 00:00:00 2001 From: Arnaud <arnaud_bouche@hotmail.com> Date: Sat, 20 Jan 2018 14:14:07 +0100 Subject: [PATCH 12/31] Modify commentaries --- cpctelera/src/video/cpct_getScreenToSprite.asm | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/cpctelera/src/video/cpct_getScreenToSprite.asm b/cpctelera/src/video/cpct_getScreenToSprite.asm index 2cc41fd48..7e21a5c94 100644 --- a/cpctelera/src/video/cpct_getScreenToSprite.asm +++ b/cpctelera/src/video/cpct_getScreenToSprite.asm @@ -1,6 +1,7 @@ ;;-----------------------------LICENSE NOTICE------------------------------------ ;; This file is part of CPCtelera: An Amstrad CPC Game Engine -;; Copyright (C) 2014-2015 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) +// Copyright (C) 2018 Arnaud BOUCHE +// Copyright (C) 2018 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) ;; ;; This program is free software: you can redistribute it and/or modify ;; it under the terms of the GNU Lesser General Public License as published by @@ -19,9 +20,9 @@ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; -;; Function: cpct_drawSpriteMasked +;; Function: cpct_getScreenToSprite ;; -;; Copies and convert part of the screen to sprite +;; Copies and convert screen area to sprite ;; ;; C Definition: ;; void <cpct_getScreenToSprite> (void* *memory*, void* *sprite*, <u8> *width*, <u8> *height*) __z88dk_callee; From 4c60a7501bb21a9adac75d0a67584e44950baa0a Mon Sep 17 00:00:00 2001 From: Arnaud <arnaud_bouche@hotmail.com> Date: Sat, 20 Jan 2018 14:14:23 +0100 Subject: [PATCH 13/31] Update cpct_getScreenToSprite.asm --- cpctelera/src/video/cpct_getScreenToSprite.asm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cpctelera/src/video/cpct_getScreenToSprite.asm b/cpctelera/src/video/cpct_getScreenToSprite.asm index 7e21a5c94..81633b7f9 100644 --- a/cpctelera/src/video/cpct_getScreenToSprite.asm +++ b/cpctelera/src/video/cpct_getScreenToSprite.asm @@ -1,7 +1,7 @@ ;;-----------------------------LICENSE NOTICE------------------------------------ ;; This file is part of CPCtelera: An Amstrad CPC Game Engine -// Copyright (C) 2018 Arnaud BOUCHE -// Copyright (C) 2018 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) +;; Copyright (C) 2018 Arnaud BOUCHE +;; Copyright (C) 2018 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) ;; ;; This program is free software: you can redistribute it and/or modify ;; it under the terms of the GNU Lesser General Public License as published by From 9712ffc39129e57d90f3e9d6039a51dc2e962022 Mon Sep 17 00:00:00 2001 From: Francisco Gallego <ronaldo@cheesetea.com> Date: Sat, 20 Jan 2018 15:10:50 +0100 Subject: [PATCH 14/31] Review getScreenToSprite code example * Change windows backlashes into standard slashes * Change some comments to better explain code * Make code conformant to code standards * Use macros where calculations can be done in compile time * Use macro constants to clarify code (like hardware colours) * Some other minor details --- examples/medium/screenCapture/src/main.c | 181 +++++++++++------------ 1 file changed, 87 insertions(+), 94 deletions(-) diff --git a/examples/medium/screenCapture/src/main.c b/examples/medium/screenCapture/src/main.c index bb2b7834f..645a184c4 100644 --- a/examples/medium/screenCapture/src/main.c +++ b/examples/medium/screenCapture/src/main.c @@ -1,7 +1,7 @@ //-----------------------------LICENSE NOTICE------------------------------------ // This file is part of CPCtelera: An Amstrad CPC Game Engine -// Copyright (C) 2017 Arnaud Bouche -// Copyright (C) 2015 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) +// Copyright (C) 2018 Arnaud Bouche +// Copyright (C) 2018 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Lesser General Public License as published by @@ -23,10 +23,10 @@ ///////////////////////////////////////////////////////////////////////////////// // SPRITES -#include "sprites\ufo.h" -#include "sprites\building_1.h" -#include "sprites\building_2.h" -#include "sprites\building_3.h" +#include "sprites/ufo.h" +#include "sprites/building_1.h" +#include "sprites/building_2.h" +#include "sprites/building_3.h" ///////////////////////////////////////////////////////////////////////////////// // USEFUL MACROS AND CONSTANTS @@ -45,17 +45,20 @@ ///////////////////////////////////////////////////////////////////////////////// // GLOBAL VARIABLES -u8 gScreenCapture[G_UFO_0_H*G_UFO_0_W]; // Array of background capture of size of UFO + +// This array will contain a copy of the background in the video memory region that +// we will be overwritting with the UFO sprite. This copy will let us erase the +// UFO sprite restoring the previous background. +u8 gScreenCapture[ G_UFO_0_H * G_UFO_0_W ]; ///////////////////////////////////////////////////////////////////////////////// // INITIALIZATION // -void Initialization() -{ - cpct_disableFirmware(); - cpct_setVideoMode(0); // Set mode 0 - cpct_setPalette (g_palette, 16); // Set the palette - cpct_setBorder(0x14); // Set the border color with Hardware color (Black) +void Initialization() { + cpct_disableFirmware(); // Disable firmware to take full control of the CPC + cpct_setVideoMode(0); // Set mode 0 + cpct_setPalette (g_palette, 16); // Set the palette + cpct_setBorder(HW_BLACK); // Set the border color with Hardware color // Fill screen with color index 4 (Red) cpct_memset(CPCT_VMEM_START, cpct_px2byteM0(4, 4), VMEM_SIZE); @@ -64,51 +67,49 @@ void Initialization() ///////////////////////////////////////////////////////////////////////////////// // GET UFO CURRENT ANIMATION SPRITE // -u8* GetUfoSprite() -{ - // Current animation state - static u8 anim = 0; - - // Array of all four sprites of UFO - static u8* const ufoSprite[] = { g_ufo_0, g_ufo_1, g_ufo_2, g_ufo_3 }; - - // Get next animation sprite and return it +u8* GetUfoSprite() { + // Private UFO Animation-Status Data + static u8 anim = 0; // Currently selected animation sprite + static u8* const ufoSprite[] = { + g_ufo_0, g_ufo_1, g_ufo_2, g_ufo_3 // Array of all four animation sprites + }; + + // Just get next animation sprite and return it return ufoSprite[anim++ % 4]; } ///////////////////////////////////////////////////////////////////////////////// // DRAW UFO // -void DrawUFO() -{ +void DrawUFO() { + // Private data to control UFO location and status static BOOL moveRight; // Keep move direction static u8 posX; // Keep position X - u8* pvmem; - - // Get VMem pointer of current UFO position for background replacement - u8* backPmem = cpct_getScreenPtr(CPCT_VMEM_START, posX, UFO_Y); - - // Move to right or to left - // If border is reached go to opposite direction - if (moveRight == FALSE) - { + // Get a pointer to the start of the UFO sprite in video memory + // previous to moving. Background will need to be restored at this + // precise location to erase UFO before drawing it in its next location + u8* pvmem_ufoBg = cpct_getScreenPtr(CPCT_VMEM_START, posX, UFO_Y); + + // Temporal pointer to videomemory for drawing sprites (will be used later) + u8* pvmem; + + // UFO Moves towards right or left + // When border is reached, movement direction changes + if (moveRight) { + // If right border reached go to left border + if (posX == SCREEN_CX - G_UFO_0_W - 1) + moveRight = FALSE; // Change direction + else + posX++; // Move to right + } else { // If left border reached go to right border - if (posX == 0) - moveRight = TRUE; // Change direction - else - posX--; // Move to left - } - else - { - // If right border reached go to left border - if (posX == SCREEN_CX - G_UFO_0_W - 1) - moveRight = FALSE; // Change direction - else - posX++; // Move to right + if (posX == 0) moveRight = TRUE; // Change direction + else posX--; // Move to left } - // Get VMem pointer of new UFO position + // Get a pointer to the Screen Video Memory location where + // UFO will be drawn next (in its new location after movement) pvmem = cpct_getScreenPtr(CPCT_VMEM_START, posX, UFO_Y); // Wait for VSync and draw background and UFO @@ -116,51 +117,48 @@ void DrawUFO() // any flickering. In other case you have to use double-buffer to prevent this. cpct_waitVSYNC(); - // Replace background with previous position + //--- UFO REDRAWING + + // Erase UFO at its previous location by drawing background over it cpct_drawSprite(gScreenCapture, backPmem, G_UFO_0_W, G_UFO_0_H); - // Memorize current background for next move + // Before drawing UFO at its new location, copy the background there + // to gScreenCapture buffer. This will let us restore it next time + // the UFO moves. cpct_getScreenToSprite(pvmem, gScreenCapture, G_UFO_0_W, G_UFO_0_H); - // Draw UFO over background redrawn + // Draw UFO at its new location cpct_drawSpriteMasked(GetUfoSprite(), pvmem, G_UFO_0_W, G_UFO_0_H); } ///////////////////////////////////////////////////////////////////////////////// // FILL LINE OF COLOR // -void FillLine(u8 pixColor, u8 lineY) -{ - // Get line start at line Y position +void FillLine(u8 pixColor, u8 lineY) { + // Get a pointer to the start of line Y of screen video memory + // and fill it with given colour u8* pvmem = cpct_getScreenPtr(CPCT_VMEM_START, 0, lineY); - - // Fill screen line width with color cpct_memset(pvmem, pixColor, SCREEN_CX); } ///////////////////////////////////////////////////////////////////////////////// -// DRAW SKY PART FILLED WITH GRADIANT +// DRAW SKY PART FILLED WITH GRADIENT // -u8 DrawSkyGradiant(u8 cy, u8 posY, u8 colorFront, u8 colorBack) -{ +u8 DrawSkyGradient(u8 cy, u8 posY, u8 colorFront, u8 colorBack) { u8 i, j; - // Get byte color M0 for front color + // Get Mode 0 screen pixel colour representations for front and back colours u8 pixFront = cpct_px2byteM0(colorFront, colorFront); - - // Get byte color M0 for back color u8 pixBack = cpct_px2byteM0(colorBack, colorBack); - // Draw gradiant zone - for (j = 0; j < cy; j++) - { + // Draw gradient zone + for (j = 0; j < cy; j++) { // If end of screen reached stop drawing if (posY == SCREEN_CY - 2) break; // Draw lines of color - for (i = 0; i < cy - j; i++) - { + for (i = 0; i < cy - j; i++) { FillLine(pixFront, posY++); } FillLine(pixBack, posY++); @@ -173,10 +171,9 @@ u8 DrawSkyGradiant(u8 cy, u8 posY, u8 colorFront, u8 colorBack) ///////////////////////////////////////////////////////////////////////////////// // DRAW SKY WITH GRADIENT ZONES FOR BACKGROUND // -void DrawSky() -{ +void DrawSky() { // Define color of gradient sky parts - const u8 colors[] = { 2, 15, 2, 7, 10, 13, 8, 4 }; + static const u8 colors[] = { 2, 15, 2, 7, 10, 13, 8, 4 }; // Current line filled with color u8 startLine = 0; @@ -184,47 +181,48 @@ void DrawSky() // Screen is divided into gradient zone u8 i; for (i = 1; i < sizeof(colors); i++) - startLine = DrawSkyGradiant(GRADIENT_CY - i, startLine, colors[i], colors[i - 1]); + startLine = DrawSkyGradient(GRADIENT_CY - i, startLine, colors[i], colors[i - 1]); } ///////////////////////////////////////////////////////////////////////////////// // DRAW CITY WITH ALL BUILDING FOR BACKGROUND // -void DrawCity() -{ - u8* pvmem = cpct_getScreenPtr(CPCT_VMEM_START, 10, SCREEN_CY - G_BUILDING_1_H); +void DrawCity() { + // As all locations of buildings are constant, we use cpctm_screenPtr that + // will calculate screen video memory pointers during compile time (as it + // is a macro). Resulting assembly code will be shorter and faster, as + // it will only contain exact video memory values for pointers, instead of + // code for calculating them. + u8* pvmem = cpctm_screenPtr(CPCT_VMEM_START, 10, SCREEN_CY - G_BUILDING_1_H); cpct_drawSprite(g_building_1, pvmem, G_BUILDING_1_W, G_BUILDING_1_H); - pvmem = cpct_getScreenPtr(CPCT_VMEM_START, 30, SCREEN_CY - G_BUILDING_2_H); + pvmem = cpctm_screenPtr(CPCT_VMEM_START, 30, SCREEN_CY - G_BUILDING_2_H); cpct_drawSprite(g_building_2, pvmem, G_BUILDING_2_W, G_BUILDING_2_H); - pvmem = cpct_getScreenPtr(CPCT_VMEM_START, 40, SCREEN_CY - G_BUILDING_1_H); + pvmem = cpctm_screenPtr(CPCT_VMEM_START, 40, SCREEN_CY - G_BUILDING_1_H); cpct_drawSprite(g_building_1, pvmem, G_BUILDING_1_W, G_BUILDING_1_H); - pvmem = cpct_getScreenPtr(CPCT_VMEM_START, 67, SCREEN_CY - G_BUILDING_2_H); + pvmem = cpctm_screenPtr(CPCT_VMEM_START, 67, SCREEN_CY - G_BUILDING_2_H); cpct_drawSprite(g_building_2, pvmem, G_BUILDING_2_W, G_BUILDING_2_H); - pvmem = cpct_getScreenPtr(CPCT_VMEM_START, 60, SCREEN_CY - G_BUILDING_3_H); + pvmem = cpctm_screenPtr(CPCT_VMEM_START, 60, SCREEN_CY - G_BUILDING_3_H); cpct_drawSprite(g_building_3, pvmem, G_BUILDING_3_W, G_BUILDING_3_H); } ///////////////////////////////////////////////////////////////////////////////// // INITIALIZE FIRST BACKGROUND CAPTURE // -void InitCapture() -{ - // Get VMem pointer of default UFO position - u8* pvmem = cpct_getScreenPtr(CPCT_VMEM_START, UFO_INIT_X, UFO_Y); - - // Capture first UFO background +void InitCapture() { + // Get Screen Video Memory pointer of default UFO location + // and make a copy of the background pixel data there to gScreenCapture buffer + u8* pvmem = cpctm_screenPtr(CPCT_VMEM_START, UFO_INIT_X, UFO_Y); cpct_getScreenToSprite(pvmem, gScreenCapture, G_UFO_0_W, G_UFO_0_H); } ///////////////////////////////////////////////////////////////////////////////// // DRAW BACKGROUND WITH GRADIENT SKY AND BUILDING // -void DrawBackground() -{ +void DrawBackground() { DrawSky(); DrawCity(); @@ -234,17 +232,12 @@ void DrawBackground() /////////////////////////////////////////////////////// /// MAIN PROGRAM /// -void main(void) -{ - // Initialize everything - Initialization(); - - // Draw background with sky and buildings - DrawBackground(); +void main(void) { + Initialization(); // Initialize everything + DrawBackground(); // Draw background with sky and buildings - // Main Loop - while(1) - { + // Main Loop: Permanently move and draw the UFO + while(1) { DrawUFO(); } } From ae535ce3b93bdf8b828bccf1cb128def09cbe464 Mon Sep 17 00:00:00 2001 From: ronaldo <ronaldo@cheesetea.com> Date: Sat, 20 Jan 2018 16:23:37 +0100 Subject: [PATCH 15/31] Completing review of getScreenToSprite example * Converting project to latest CPCtelera project version * Using spaces instead of tabs for indenting --- .../medium/screenCapture/.vscode/tasks.json | 58 ++++ .../medium/screenCapture/cfg/build_config.mk | 2 + .../screenCapture/cfg/image_conversion.mk | 12 +- .../screenCapture/cfg/music_conversion.mk | 53 ++++ .../screenCapture/cfg/tilemap_conversion.mk | 66 ++++ examples/medium/screenCapture/src/main.c | 282 +++++++++--------- 6 files changed, 323 insertions(+), 150 deletions(-) create mode 100644 examples/medium/screenCapture/.vscode/tasks.json create mode 100644 examples/medium/screenCapture/cfg/music_conversion.mk create mode 100644 examples/medium/screenCapture/cfg/tilemap_conversion.mk diff --git a/examples/medium/screenCapture/.vscode/tasks.json b/examples/medium/screenCapture/.vscode/tasks.json new file mode 100644 index 000000000..0285f7abe --- /dev/null +++ b/examples/medium/screenCapture/.vscode/tasks.json @@ -0,0 +1,58 @@ +//-----------------------------LICENSE NOTICE------------------------------------ +// This file is part of CPCtelera: An Amstrad CPC Game Engine +// Copyright (C) 2017 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +//------------------------------------------------------------------------------{ +// See https://go.microsoft.com/fwlink/?LinkId=733558 +// for the documentation about the tasks.json format +{ + "version": "0.1.0" + , "command": "make" + , "isShellCommand": true + , "args": [] + , "showOutput": "always" + , "suppressTaskName": true + , "tasks": [ + { + "taskName": "make" + , "args": [] + , "isBuildCommand": true + , "problemMatcher": { + "owner": "base" + , "fileLocation": ["relative", "${workspaceRoot}"] + , "pattern": { + "regexp": "^(.*):(\\d+):\\s+(warning|error|syntax error)[^:]*:\\s+(.*)$" + , "file": 1 + , "line": 2 + , "severity": 3 + , "message": 4 + } + } + } + , { + "taskName": "clean" + , "args": ["clean"] + } + , { + "taskName": "cleanall" + , "args": ["cleanall"] + } + , { + "taskName": "run" + , "command": "cpct_winape" + , "args": [ "-a" ] + } + ] +} \ No newline at end of file diff --git a/examples/medium/screenCapture/cfg/build_config.mk b/examples/medium/screenCapture/cfg/build_config.mk index 2b1854740..101220652 100644 --- a/examples/medium/screenCapture/cfg/build_config.mk +++ b/examples/medium/screenCapture/cfg/build_config.mk @@ -139,6 +139,8 @@ include $(CPCT_PATH)/cfg/global_functions.mk # Convert images and tilemaps include cfg/image_conversion.mk +include cfg/tilemap_conversion.mk +include cfg/music_conversion.mk # Calculate all subdirectories SUBDIRS := $(filter-out ., $(shell find $(SRCDIR) -type d -print)) diff --git a/examples/medium/screenCapture/cfg/image_conversion.mk b/examples/medium/screenCapture/cfg/image_conversion.mk index 754e3b5d2..6c4a775ae 100644 --- a/examples/medium/screenCapture/cfg/image_conversion.mk +++ b/examples/medium/screenCapture/cfg/image_conversion.mk @@ -54,18 +54,10 @@ ## $(eval $(call IMG2SPRITES,imgs/1.png,0,g,4,8,$(PAL),,src/)) ## ############################################################################ -## Example firmware palette definition as variable in cpct_img2tileset format - +## Firmware palette definition as variable in cpct_img2tileset format PALETTE={13 1 2 3 6 9 10 11 15 19 20 21 24 25 26 0} -## Example image conversion -## This example would convert img/example.png into src/example.{c|h} files. -## A C-array called pre_example[24*12*2] would be generated with the definition -## of the image example.png in mode 0 screen pixel format, with interlaced mask. -## The palette used for conversion is given through the PALETTE variable and -## a pre_palette[16] array will be generated with the 16 palette colours as -## hardware colour values. - +## Automatic conversion for UFO and Buildings sprites for Mode0 pixel format $(eval $(call IMG2SPRITES,img/ufo.png,0,g,32,0,$(PALETTE),mask,src/sprites,hwpalette)) $(eval $(call IMG2SPRITES,img/building_1.png,0,g,0,0,$(PALETTE),,src/sprites,)) $(eval $(call IMG2SPRITES,img/building_2.png,0,g,0,0,$(PALETTE),,src/sprites,)) diff --git a/examples/medium/screenCapture/cfg/music_conversion.mk b/examples/medium/screenCapture/cfg/music_conversion.mk new file mode 100644 index 000000000..f86085c7d --- /dev/null +++ b/examples/medium/screenCapture/cfg/music_conversion.mk @@ -0,0 +1,53 @@ +##-----------------------------LICENSE NOTICE------------------------------------ +## This file is part of CPCtelera: An Amstrad CPC Game Engine +## Copyright (C) 2016 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) +## +## This program is free software: you can redistribute it and/or modify +## it under the terms of the GNU Lesser General Public License as published by +## the Free Software Foundation, either version 3 of the License, or +## (at your option) any later version. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU Lesser General Public License for more details. +## +## You should have received a copy of the GNU Lesser General Public License +## along with this program. If not, see <http://www.gnu.org/licenses/>. +##------------------------------------------------------------------------------ + +############################################################################ +## CPCTELERA ENGINE ## +## Automatic image conversion file ## +##------------------------------------------------------------------------## +## This file is intended for users to automate music conversion from ## +## original files (like Arkos Tracker .aks) into data arrays. ## +## ## +## Macro used for conversion is AKS2C, which has up to 5 parameters: ## +## (1): AKS file to be converted to data array ## +## (2): C identifier for the generated data array (will have underscore ## +## in front in ASM) ## +## (3): Output folder for .s and .h files generated (Default same folder)## +## (4): Memory address where music data will be loaded ## +## (5): Aditional options (you can use this to pass aditional modifiers ## +## to cpct_aks2c) ## +## ## +## Macro is used in this way (one line for each image to be converted): ## +## $(eval $(call AKS2C,(1),(2),(3),(4),(5)) ## +## ## +## Important: ## +## * Do NOT separate macro parameters with spaces, blanks or other chars.## +## ANY character you put into a macro parameter will be passed to the ## +## macro. Therefore ...,src/music,... will represent "src/music" ## +## folder, whereas ..., src/music,... means " src/sprites" folder. ## +## * You can omit parameters by leaving them empty. ## +## * Parameter (5) (Aditional options) is optional and generally not ## +## required. ## +############################################################################ + +## Convert music/song.aks to src/music/song.s and src/music/song.h +## This file contains a music created with Arkos Tracker. This macro +## will convert the music into a data array called g_mysong that will be +## placed at the 0x42A0 memory address in an absolue way. +## +#$(eval $(call AKS2C,music/song.aks,g_mysong,src/music/,0x42A0)) \ No newline at end of file diff --git a/examples/medium/screenCapture/cfg/tilemap_conversion.mk b/examples/medium/screenCapture/cfg/tilemap_conversion.mk new file mode 100644 index 000000000..21f7d929b --- /dev/null +++ b/examples/medium/screenCapture/cfg/tilemap_conversion.mk @@ -0,0 +1,66 @@ +##-----------------------------LICENSE NOTICE------------------------------------ +## This file is part of CPCtelera: An Amstrad CPC Game Engine +## Copyright (C) 2016 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) +## +## This program is free software: you can redistribute it and/or modify +## it under the terms of the GNU Lesser General Public License as published by +## the Free Software Foundation, either version 3 of the License, or +## (at your option) any later version. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU Lesser General Public License for more details. +## +## You should have received a copy of the GNU Lesser General Public License +## along with this program. If not, see <http://www.gnu.org/licenses/>. +##------------------------------------------------------------------------------ + +############################################################################ +## CPCTELERA ENGINE ## +## Automatic image conversion file ## +##------------------------------------------------------------------------## +## This file is intended for users to automate tilemap conversion from ## +## original files (like Tiled .tmx) into C-arrays. ## +## ## +## Macro used for conversion is TMX2C, which has up to 4 parameters: ## +## (1): TMX file to be converted to C array ## +## (2): C identifier for the generated C array ## +## (3): Output folder for C and H files generated (Default same folder) ## +## (4): Bits per item (1,2,4 or 6 to codify tilemap into a bitarray). ## +## Blanck for normal integer tilemap array (8 bits per item) ## +## (5): Aditional options (aditional modifiers for cpct_tmx2csv) ## +## ## +## Macro is used in this way (one line for each image to be converted): ## +## $(eval $(call TMX2C,(1),(2),(3),(4),(5))) ## +## ## +## Important: ## +## * Do NOT separate macro parameters with spaces, blanks or other chars.## +## ANY character you put into a macro parameter will be passed to the ## +## macro. Therefore ...,src/sprites,... will represent "src/sprites" ## +## folder, whereas ..., src/sprites,... means " src/sprites" folder. ## +## * You can omit parameters by leaving them empty. ## +## * Parameters (4) and (5) are optional and generally not required. ## +############################################################################ + +## Conversion Examples +## + +## Convert img/tilemap.tmx to src/tilemap.c and src/tilemap.h +## This file contains a tilemap created with Tiled that uses tiles +## in img/tiles.png. This macro will convert the tilemap into a C-array +## named g_tilemap, containing all the IDs of the tiles that are located +## at each given location of the C-array. +## + +#$(eval $(call TMX2C,img/tilemap.tmx,g_tilemap,src/,4)) + +## Convert img/level0b.tmx to src/levels/level0b.c and src/levels/level0b.h +## This file contains another tilemap created with Tiled. This macro +## will convert the tilemap into a C bitarray of 4-bits per item. The array +## will be named g_level0_4bit. For each tile ID included into the final +## bitarray, only 4 bits will be used. Therefore, each byte of the array +## will contain 2 tile IDs. +## + +#$(eval $(call TMX2C,img/level0b.tmx,g_level0_4bit,src/levels/,4)) \ No newline at end of file diff --git a/examples/medium/screenCapture/src/main.c b/examples/medium/screenCapture/src/main.c index 645a184c4..9b39ada61 100644 --- a/examples/medium/screenCapture/src/main.c +++ b/examples/medium/screenCapture/src/main.c @@ -31,17 +31,17 @@ ///////////////////////////////////////////////////////////////////////////////// // USEFUL MACROS AND CONSTANTS // -#define BOOL u8 -#define TRUE 1 -#define FALSE 0 +#define BOOL u8 +#define TRUE 1 +#define FALSE 0 -#define SCREEN_CY 200 -#define SCREEN_CX 80 -#define VMEM_SIZE 0x4000 +#define SCREEN_CY 200 +#define SCREEN_CX 80 +#define VMEM_SIZE 0x4000 -#define UFO_Y 120 -#define UFO_INIT_X 0 -#define GRADIENT_CY 10 +#define UFO_Y 120 +#define UFO_INIT_X 0 +#define GRADIENT_CY 10 ///////////////////////////////////////////////////////////////////////////////// // GLOBAL VARIABLES @@ -49,33 +49,33 @@ // This array will contain a copy of the background in the video memory region that // we will be overwritting with the UFO sprite. This copy will let us erase the // UFO sprite restoring the previous background. -u8 gScreenCapture[ G_UFO_0_H * G_UFO_0_W ]; +u8 gScreenCapture[ G_UFO_0_H * G_UFO_0_W ]; ///////////////////////////////////////////////////////////////////////////////// // INITIALIZATION // void Initialization() { - cpct_disableFirmware(); // Disable firmware to take full control of the CPC - cpct_setVideoMode(0); // Set mode 0 - cpct_setPalette (g_palette, 16); // Set the palette - cpct_setBorder(HW_BLACK); // Set the border color with Hardware color - - // Fill screen with color index 4 (Red) - cpct_memset(CPCT_VMEM_START, cpct_px2byteM0(4, 4), VMEM_SIZE); + cpct_disableFirmware(); // Disable firmware to take full control of the CPC + cpct_setVideoMode(0); // Set mode 0 + cpct_setPalette (g_palette, 16); // Set the palette + cpct_setBorder(HW_BLACK); // Set the border color with Hardware color + + // Fill screen with color index 4 (Red) + cpct_memset(CPCT_VMEM_START, cpct_px2byteM0(4, 4), VMEM_SIZE); } ///////////////////////////////////////////////////////////////////////////////// // GET UFO CURRENT ANIMATION SPRITE // u8* GetUfoSprite() { - // Private UFO Animation-Status Data - static u8 anim = 0; // Currently selected animation sprite - static u8* const ufoSprite[] = { - g_ufo_0, g_ufo_1, g_ufo_2, g_ufo_3 // Array of all four animation sprites - }; + // Private UFO Animation-Status Data + static u8 anim = 0; // Currently selected animation sprite + static u8* const ufoSprite[] = { + g_ufo_0, g_ufo_1, g_ufo_2, g_ufo_3 // Array of all four animation sprites + }; - // Just get next animation sprite and return it - return ufoSprite[anim++ % 4]; + // Just get next animation sprite and return it + return ufoSprite[anim++ % 4]; } ///////////////////////////////////////////////////////////////////////////////// @@ -83,161 +83,163 @@ u8* GetUfoSprite() { // void DrawUFO() { // Private data to control UFO location and status - static BOOL moveRight; // Keep move direction - static u8 posX; // Keep position X - - // Get a pointer to the start of the UFO sprite in video memory - // previous to moving. Background will need to be restored at this - // precise location to erase UFO before drawing it in its next location - u8* pvmem_ufoBg = cpct_getScreenPtr(CPCT_VMEM_START, posX, UFO_Y); - - // Temporal pointer to videomemory for drawing sprites (will be used later) - u8* pvmem; - - // UFO Moves towards right or left - // When border is reached, movement direction changes - if (moveRight) { - // If right border reached go to left border - if (posX == SCREEN_CX - G_UFO_0_W - 1) - moveRight = FALSE; // Change direction - else - posX++; // Move to right - } else { - // If left border reached go to right border - if (posX == 0) moveRight = TRUE; // Change direction - else posX--; // Move to left - } - - // Get a pointer to the Screen Video Memory location where - // UFO will be drawn next (in its new location after movement) - pvmem = cpct_getScreenPtr(CPCT_VMEM_START, posX, UFO_Y); - - // Wait for VSync and draw background and UFO - // This drawing operation is fast enough not to be caught by the raster, and does not produce - // any flickering. In other case you have to use double-buffer to prevent this. - cpct_waitVSYNC(); - - //--- UFO REDRAWING + static BOOL moveRight; // Keep move direction + static u8 posX; // Keep position X + + // Get a pointer to the start of the UFO sprite in video memory + // previous to moving. Background will need to be restored at this + // precise location to erase UFO before drawing it in its next location + u8* pvmem_ufoBg = cpct_getScreenPtr(CPCT_VMEM_START, posX, UFO_Y); + + // Temporal pointer to videomemory for drawing sprites (will be used later) + u8* pvmem; + + // UFO Moves towards right or left + // When border is reached, movement direction changes + if (moveRight) { + // If right border reached go to left border + if (posX == SCREEN_CX - G_UFO_0_W) + moveRight = FALSE; // Change direction + else + posX++; // Move to right + } else { + // If left border reached go to right border + if (posX == 0) moveRight = TRUE; // Change direction + else posX--; // Move to left + } + + // Get a pointer to the Screen Video Memory location where + // UFO will be drawn next (in its new location after movement) + pvmem = cpct_getScreenPtr(CPCT_VMEM_START, posX, UFO_Y); + + // Wait for VSync and draw background and UFO + // This drawing operation is fast enough not to be caught by the raster, and does not produce + // any flickering. In other case you have to use double-buffer to prevent this. + cpct_waitVSYNC(); + + //--- UFO REDRAWING - // Erase UFO at its previous location by drawing background over it - cpct_drawSprite(gScreenCapture, backPmem, G_UFO_0_W, G_UFO_0_H); - - // Before drawing UFO at its new location, copy the background there - // to gScreenCapture buffer. This will let us restore it next time - // the UFO moves. - cpct_getScreenToSprite(pvmem, gScreenCapture, G_UFO_0_W, G_UFO_0_H); - - // Draw UFO at its new location - cpct_drawSpriteMasked(GetUfoSprite(), pvmem, G_UFO_0_W, G_UFO_0_H); + // Erase UFO at its previous location by drawing background over it + cpct_drawSprite(gScreenCapture, pvmem_ufoBg, G_UFO_0_W, G_UFO_0_H); + + // Before drawing UFO at its new location, copy the background there + // to gScreenCapture buffer. This will let us restore it next time + // the UFO moves. + cpct_getScreenToSprite(pvmem, gScreenCapture, G_UFO_0_W, G_UFO_0_H); + + // Draw UFO at its new location + cpct_drawSpriteMasked(GetUfoSprite(), pvmem, G_UFO_0_W, G_UFO_0_H); } ///////////////////////////////////////////////////////////////////////////////// // FILL LINE OF COLOR // void FillLine(u8 pixColor, u8 lineY) { - // Get a pointer to the start of line Y of screen video memory - // and fill it with given colour - u8* pvmem = cpct_getScreenPtr(CPCT_VMEM_START, 0, lineY); - cpct_memset(pvmem, pixColor, SCREEN_CX); + // Get a pointer to the start of line Y of screen video memory + // and fill it with given colour + u8* pvmem = cpct_getScreenPtr(CPCT_VMEM_START, 0, lineY); + cpct_memset(pvmem, pixColor, SCREEN_CX); } ///////////////////////////////////////////////////////////////////////////////// // DRAW SKY PART FILLED WITH GRADIENT // u8 DrawSkyGradient(u8 cy, u8 posY, u8 colorFront, u8 colorBack) { - u8 i, j; - - // Get Mode 0 screen pixel colour representations for front and back colours - u8 pixFront = cpct_px2byteM0(colorFront, colorFront); - u8 pixBack = cpct_px2byteM0(colorBack, colorBack); - - // Draw gradient zone - for (j = 0; j < cy; j++) { - // If end of screen reached stop drawing - if (posY == SCREEN_CY - 2) - break; - - // Draw lines of color - for (i = 0; i < cy - j; i++) { - FillLine(pixFront, posY++); - } - FillLine(pixBack, posY++); - } - - // Return ending line colorized - return posY; + u8 i, j; + + // Get Mode 0 screen pixel colour representations for front and back colours + u8 pixFront = cpct_px2byteM0(colorFront, colorFront); + u8 pixBack = cpct_px2byteM0(colorBack, colorBack); + + // Draw gradient zone + for (j = 0; j < cy; j++) { + // If end of screen reached stop drawing + if (posY == SCREEN_CY - 2) + break; + + // Draw lines of color + for (i = 0; i < cy - j; i++) { + FillLine(pixFront, posY++); + } + FillLine(pixBack, posY++); + } + + // Return ending line colorized + return posY; } ///////////////////////////////////////////////////////////////////////////////// // DRAW SKY WITH GRADIENT ZONES FOR BACKGROUND // void DrawSky() { - // Define color of gradient sky parts - static const u8 colors[] = { 2, 15, 2, 7, 10, 13, 8, 4 }; - - // Current line filled with color - u8 startLine = 0; - - // Screen is divided into gradient zone - u8 i; - for (i = 1; i < sizeof(colors); i++) - startLine = DrawSkyGradient(GRADIENT_CY - i, startLine, colors[i], colors[i - 1]); + // Define color of gradient sky parts + static const u8 colors[] = { 2, 15, 2, 7, 10, 13, 8, 4 }; + + // Current line filled with color + u8 startLine = 0; + + // Screen is divided into gradient zone + u8 i; + for (i = 1; i < sizeof(colors); i++) + startLine = DrawSkyGradient(GRADIENT_CY - i, startLine, colors[i], colors[i - 1]); } ///////////////////////////////////////////////////////////////////////////////// // DRAW CITY WITH ALL BUILDING FOR BACKGROUND // void DrawCity() { - // As all locations of buildings are constant, we use cpctm_screenPtr that - // will calculate screen video memory pointers during compile time (as it - // is a macro). Resulting assembly code will be shorter and faster, as - // it will only contain exact video memory values for pointers, instead of - // code for calculating them. - u8* pvmem = cpctm_screenPtr(CPCT_VMEM_START, 10, SCREEN_CY - G_BUILDING_1_H); - cpct_drawSprite(g_building_1, pvmem, G_BUILDING_1_W, G_BUILDING_1_H); - - pvmem = cpctm_screenPtr(CPCT_VMEM_START, 30, SCREEN_CY - G_BUILDING_2_H); - cpct_drawSprite(g_building_2, pvmem, G_BUILDING_2_W, G_BUILDING_2_H); - - pvmem = cpctm_screenPtr(CPCT_VMEM_START, 40, SCREEN_CY - G_BUILDING_1_H); - cpct_drawSprite(g_building_1, pvmem, G_BUILDING_1_W, G_BUILDING_1_H); - - pvmem = cpctm_screenPtr(CPCT_VMEM_START, 67, SCREEN_CY - G_BUILDING_2_H); - cpct_drawSprite(g_building_2, pvmem, G_BUILDING_2_W, G_BUILDING_2_H); - - pvmem = cpctm_screenPtr(CPCT_VMEM_START, 60, SCREEN_CY - G_BUILDING_3_H); - cpct_drawSprite(g_building_3, pvmem, G_BUILDING_3_W, G_BUILDING_3_H); + u8* pvmem; + + // As all locations of buildings are constant, we use cpctm_screenPtr that + // will calculate screen video memory pointers during compile time (as it + // is a macro). Resulting assembly code will be shorter and faster, as + // it will only contain exact video memory values for pointers, instead of + // code for calculating them. + pvmem = cpctm_screenPtr(CPCT_VMEM_START, 10, SCREEN_CY - G_BUILDING_1_H); + cpct_drawSprite(g_building_1, pvmem, G_BUILDING_1_W, G_BUILDING_1_H); + + pvmem = cpctm_screenPtr(CPCT_VMEM_START, 30, SCREEN_CY - G_BUILDING_2_H); + cpct_drawSprite(g_building_2, pvmem, G_BUILDING_2_W, G_BUILDING_2_H); + + pvmem = cpctm_screenPtr(CPCT_VMEM_START, 40, SCREEN_CY - G_BUILDING_1_H); + cpct_drawSprite(g_building_1, pvmem, G_BUILDING_1_W, G_BUILDING_1_H); + + pvmem = cpctm_screenPtr(CPCT_VMEM_START, 67, SCREEN_CY - G_BUILDING_2_H); + cpct_drawSprite(g_building_2, pvmem, G_BUILDING_2_W, G_BUILDING_2_H); + + pvmem = cpctm_screenPtr(CPCT_VMEM_START, 60, SCREEN_CY - G_BUILDING_3_H); + cpct_drawSprite(g_building_3, pvmem, G_BUILDING_3_W, G_BUILDING_3_H); } ///////////////////////////////////////////////////////////////////////////////// -// INITIALIZE FIRST BACKGROUND CAPTURE +// INITIALIZE FIRST BACKGROUND CAPTURE // void InitCapture() { - // Get Screen Video Memory pointer of default UFO location - // and make a copy of the background pixel data there to gScreenCapture buffer - u8* pvmem = cpctm_screenPtr(CPCT_VMEM_START, UFO_INIT_X, UFO_Y); - cpct_getScreenToSprite(pvmem, gScreenCapture, G_UFO_0_W, G_UFO_0_H); + // Get Screen Video Memory pointer of default UFO location + // and make a copy of the background pixel data there to gScreenCapture buffer + u8* pvmem = cpctm_screenPtr(CPCT_VMEM_START, UFO_INIT_X, UFO_Y); + cpct_getScreenToSprite(pvmem, gScreenCapture, G_UFO_0_W, G_UFO_0_H); } ///////////////////////////////////////////////////////////////////////////////// -// DRAW BACKGROUND WITH GRADIENT SKY AND BUILDING +// DRAW BACKGROUND WITH GRADIENT SKY AND BUILDING // void DrawBackground() { - DrawSky(); - DrawCity(); - - InitCapture(); + DrawSky(); + DrawCity(); + + InitCapture(); } /////////////////////////////////////////////////////// /// MAIN PROGRAM /// void main(void) { - Initialization(); // Initialize everything - DrawBackground(); // Draw background with sky and buildings - - // Main Loop: Permanently move and draw the UFO - while(1) { - DrawUFO(); - } + Initialization(); // Initialize everything + DrawBackground(); // Draw background with sky and buildings + + // Main Loop: Permanently move and draw the UFO + while(1) { + DrawUFO(); + } } From 6463716cd83557e05408fc054d85f708ae0c3609 Mon Sep 17 00:00:00 2001 From: ronaldo <ronaldo@cheesetea.com> Date: Sat, 20 Jan 2018 17:54:00 +0100 Subject: [PATCH 16/31] Added gitignore for generated sprites --- examples/medium/screenCapture/.gitignore | 1 + 1 file changed, 1 insertion(+) create mode 100644 examples/medium/screenCapture/.gitignore diff --git a/examples/medium/screenCapture/.gitignore b/examples/medium/screenCapture/.gitignore new file mode 100644 index 000000000..f9e0cbe8a --- /dev/null +++ b/examples/medium/screenCapture/.gitignore @@ -0,0 +1 @@ +src/sprites/ From b3e799448940a8e678b6f984fa3e77fcf99d3de9 Mon Sep 17 00:00:00 2001 From: ronaldo <ronaldo@cheesetea.com> Date: Sat, 20 Jan 2018 17:55:57 +0100 Subject: [PATCH 17/31] Improved getScreenToSprite implementation * Shorter and faster version * Completely reviewed documentation --- .../src/video/cpct_getScreenToSprite.asm | 319 ++++++++++-------- .../cpct_getScreenToSprite_asmbindings.s | 7 +- .../video/cpct_getScreenToSprite_cbindings.s | 11 +- 3 files changed, 193 insertions(+), 144 deletions(-) diff --git a/cpctelera/src/video/cpct_getScreenToSprite.asm b/cpctelera/src/video/cpct_getScreenToSprite.asm index 81633b7f9..5c8920ae8 100644 --- a/cpctelera/src/video/cpct_getScreenToSprite.asm +++ b/cpctelera/src/video/cpct_getScreenToSprite.asm @@ -1,132 +1,187 @@ -;;-----------------------------LICENSE NOTICE------------------------------------ -;; This file is part of CPCtelera: An Amstrad CPC Game Engine -;; Copyright (C) 2018 Arnaud BOUCHE -;; Copyright (C) 2018 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) -;; -;; This program is free software: you can redistribute it and/or modify -;; it under the terms of the GNU Lesser General Public License as published by -;; the Free Software Foundation, either version 3 of the License, or -;; (at your option) any later version. -;; -;; This program is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU Lesser General Public License for more details. -;; -;; You should have received a copy of the GNU Lesser General Public License -;; along with this program. If not, see <http://www.gnu.org/licenses/>. -;;------------------------------------------------------------------------------- -.module cpct_sprites - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; -;; Function: cpct_getScreenToSprite -;; -;; Copies and convert screen area to sprite -;; -;; C Definition: -;; void <cpct_getScreenToSprite> (void* *memory*, void* *sprite*, <u8> *width*, <u8> *height*) __z88dk_callee; -;; -;; Input Parameters (6 bytes): -;; (2B DE) memory - Source Screen Address (Video memory location) -;; (2B HL) sprite - Destination Sprite Address (Sprite data array) -;; (1B C ) width - Sprite Width in *bytes* (>0) (Beware, *not* in pixels!) -;; (1B B ) height - Sprite Height in bytes (>0) -;; -;; Assembly call (Input parameters on registers): -;; > call cpct_getScreenToSprite_asm -;; -;; Parameter Restrictions: -;; * *memory* could be any place in memory, inside or outside current video memory. It -;; will be equally treated as video memory (taking into account CPC's video memory -;; disposition). This lets you copy software or hardware backbuffers, and -;; not only video memory. -;; * *sprite* must be an array containing sprite's pixels data in screen pixel format -;; * *width* must be the width of the screen to capture *in bytes*, and -;; must be 1 or more. Using 0 as *width* parameter for this function could potentially -;; make the program hang or crash. Always remember that the *width* must be -;; expressed in bytes and *not* in pixels. The correspondence is: -;; mode 0 - 1 byte = 2 pixels -;; modes 1 / 3 - 1 byte = 4 pixels -;; mode 2 - 1 byte = 8 pixels -;; * *height* must be the height of the sprite in bytes, and must be greater than 0. -;; There is no practical upper limit to this value. Height of a sprite in -;; bytes and pixels is the same value, as bytes only group consecutive pixels in -;; the horizontal space. -;; -;; Known limitations: -;; * This function does not do any kind of boundary check or clipping. If you -;; get data beyond your video memory or screen buffer the sprite will also contains -;; not video data. -;; -;; Details: -;; This function copies a video-memory location (either present video-memory or software / hardware -;; backbuffer) to a generic WxH bytes sprite from memory to . The destination sprite must be stored as an array (i.e. with -;; all of its pixels stored as consecutive bytes in memory). -;; -;; Destroyed Register values: -;; AF, BC, DE, HL -;; -;; Required memory: -;; C-bindings - 50 bytes -;; ASM-bindints - 44 bytes -;; -;; Time Measures: -;; (start code) -;; Case | microSecs (us) | CPU Cycles -;; ---------------------------------------------------------------- -;; Best | 16 + (27 + 12W)H | 84 + (88 + 72W)H -;; ---------------------------------------------------------------- -;; W=2,H=16 | 832 | 3328 -;; W=4,H=32 | 2416 | 9964 -;; ---------------------------------------------------------------- -;; Asm saving | -16 | -64 -;; ---------------------------------------------------------------- -;; (end code) -;; W = *width* in bytes, H = *height* in bytes -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - - push ix ;; [5] Save IX regiter before using it as temporal var - ld__ixl_c ;; [3] Save Sprite Width into IXL for later use - -dms_sprite_height_loop: - push de ;; [4] Save DE for later use (jump to next screen line) - -dms_sprite_width_loop: - ld a, (de) ;; [2] Get Screen byte into A - ld (hl), a ;; [2] Put A (Screen) byte into Sprite Memory - inc de ;; [2] Next Screen Memory byte - inc hl ;; [2] Next Sprite byte - - dec c ;; [1] C holds sprite width, we decrease it to count pixels in this line. - jr nz,dms_sprite_width_loop;; [2/3] While not 0, we are still painting this sprite line - ;; - When 0, we have to jump to next pixel line - - pop de ;; [3] Recover DE from stack. We use it to calculate start of next pixel line on screen - - dec b ;; [1] B holds sprite height. We decrease it to count another pixel line finished - jr z,dms_sprite_copy_ended;; [2/3] If 0, we have finished the last sprite line. - ;; - If not 0, we have to move pointers to the next pixel line - - ld__c_ixl ;; [3] Restore Sprite Width into C - - ld a, d ;; [1] Start of next pixel line normally is 0x0800 bytes away. - add #0x08 ;; [2] so we add it to DE (just by adding 0x08 to D) - ld d, a ;; [1] - and #0x38 ;; [2] We check if we have crossed memory boundary (every 8 pixel lines) - jr nz, dms_sprite_height_loop ;; [2/3] by checking the 4 bits that identify present memory line. - ;; .... If 0, we have crossed boundaries - -dms_sprite_8bit_boundary_crossed: - ld a, e ;; [1] DE = DE + 0xC050h - add #0x50 ;; [2] -- Relocate DE pointer to the start of the next pixel line: - ld e, a ;; [1] -- DE is moved forward 3 memory banks plus 50 bytes (4000h * 3) - ld a, d ;; [1] -- which effectively is the same as moving it 1 bank backwards and then - adc #0xC0 ;; [2] -- 50 bytes forwards (which is what we want to move it to the next pixel line) - ld d, a ;; [1] -- Calculations are made with 8 bit maths as it is faster than other alternatives here - - jr dms_sprite_height_loop ;; [3] Jump to continue with next pixel line - -dms_sprite_copy_ended: - pop ix ;; [5] Restore IX before returning - ret ;; [3] Return to caller +;;-----------------------------LICENSE NOTICE------------------------------------ +;; This file is part of CPCtelera: An Amstrad CPC Game Engine +;; Copyright (C) 2018 Arnaud BOUCHE +;; Copyright (C) 2018 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) +;; +;; This program is free software: you can redistribute it and/or modify +;; it under the terms of the GNU Lesser General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU Lesser General Public License for more details. +;; +;; You should have received a copy of the GNU Lesser General Public License +;; along with this program. If not, see <http://www.gnu.org/licenses/>. +;;------------------------------------------------------------------------------- +.module cpct_sprites + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; +;; Function: cpct_getScreenToSprite +;; +;; Copies sprite data from screen video memory to a linear array (a sprite) +;; +;; C Definition: +;; void <cpct_getScreenToSprite> (void* *memory*, void* *sprite*, <u8> *width*, <u8> *height*) __z88dk_callee; +;; +;; Input Parameters (6 bytes): +;; (2B HL) memory - Source Screen Address (Video memory location) +;; (2B DE) sprite - Destination Sprite Address (Sprite data array) +;; (1B C ) width - Sprite Width in *bytes* (>0) (Beware, *not* in pixels!) +;; (1B B ) height - Sprite Height in bytes (>0) +;; +;; Assembly call (Input parameters on registers): +;; > call cpct_getScreenToSprite_asm +;; +;; Parameter Restrictions: +;; * *memory* could be any place in memory, inside or outside current video memory. It +;; will be equally treated as video memory (taking into account CPC's video memory +;; disposition). This lets you copy software or hardware backbuffers, and +;; not only video memory. +;; * *sprite* must be a pointer to the start of a linear array that will be filled +;; up with sprite pixel data got from *memory*. +;; * *width* must be the width of the screen to capture *in bytes*, and +;; must be greater than 0. A 0 as *width* parameter will be considered as 65536, +;; making this function overwrite the whole memory, making your program crash. +;; * *height* must be the height of the sprite in bytes, and must be greater than 0. +;; A 0 as *height* parameter will be considered as 256 (the maximum value). +;; Height of a sprite in bytes and pixels is the same value, as bytes only group +;; consecutive pixels in the horizontal space. +;; +;; Known limitations: +;; * This function does not do any kind of boundary check or clipping. If you +;; get data beyond your video memory or screen buffer the sprite will also contains +;; not video data. +;; * This function uses self-modifying code, so it cannot be used from ROM. +;; +;; Details: +;; Reads screen video memory data at *memory* and copies it to a linear array (a *sprite*). +;; The copy takes into account CPC's video memory disposition, which is comprised of character +;; lines made by 8-pixel lines each. The copy converts this disposition to linear, putting +;; each sprite line contiguous to the previous one in the resulting *sprite* array. After +;; this copy, *sprite* can be used as any other normal sprite through sprite drawing functions +;; like <cpct_drawSprite>. +;; +;; Next example shows how to use this function, +;; (start code) +;; // All enemies will be of the same size +;; #define ENEMY_WIDTH 6 +;; #define ENEMY_HEIGHT 10 +;; +;; // Struct Enemy +;; // Contains all enemy information: position, velocity, sprite and background data buffer. +;; // The background data buffer will contain the background screen pixel data behind the +;; // enemy sprite. This will be used to erase the enemy sprite restoring the background. +;; typedef struct Enemy { +;; u8 x, y; // Enemy location +;; u8 vx, vy; // Enemy velocity +;; u8* sprite; // Enemy sprite +;; u8 background[ ENEMY_WIDTH * ENEMY_HEIGHT ]; // Background pixel data +;; } Enemy; +;; +;; ////////////////////////////////////////////////////////////////////////////////////////// +;; // Moves an Enemy and redraws it afterwards +;; // +;; void MoveAndRedrawEnemy(Enemy* enemy) { +;; u8* pvmem; // Temporal pointer to video memory for drawing sprites (will be used later) +;; +;; // --- Calculations previous to moving the enemy --- +;; +;; // Get a pointer to the start of the Enemy sprite in video memory +;; // previous to moving. Background will need to be restored at this +;; // precise location to erase the Enemy before drawing it in its next location +;; u8* pvmem_enemyBg = cpct_getScreenPtr(CPCT_VMEM_START, enemy->x, enemy->y); +;; +;; // Move the enemy adding velocity to position +;; enemy->x += enemy->vx; +;; enemy->y += enemy->vy; +;; +;; // Get a pointer to the Screen Video Memory location where +;; // Enemy will be drawn next (in its new location after movement) +;; pvmem = cpct_getScreenPtr(CPCT_VMEM_START, enemy->x, enemy->y); +;; +;; // Wait for VSync and draw background and Enemy +;; cpct_waitVSYNC(); +;; +;; //--- ENEMY REDRAWING --- +;; +;; // Erase ENEMY at its previous location by drawing background over it +;; cpct_drawSprite(enemy->background, pvmem_enemyBg, ENEMY_WIDTH, ENEMY_HEIGHT); +;; +;; // Before drawing ENEMY at its new location, copy the background there +;; // to enemy->background buffer. This will let us restore it next time the ENEMY moves. +;; cpct_getScreenToSprite(pvmem, enemy->background, ENEMY_WIDTH, ENEMY_HEIGHT); +;; +;; // Draw ENEMY at its new location +;; cpct_drawSpriteMasked(enemy->sprite, pvmem, ENEMY_WIDTH, ENEMY_HEIGHT); +;; } +;; (end code) +;; +;; +;; Destroyed Register values: +;; AF, BC, DE, HL +;; +;; Required memory: +;; C-bindings - 39 bytes +;; ASM-bindings - 34 bytes +;; +;; Time Measures: +;; (start code) +;; Case | microSecs (us) | CPU Cycles +;; ---------------------------------------------------------------- +;; Best | 30 + 8HH + (19 + 6W)H | 120 + 32HH + (76 + 24W)H +;; Worst | 38 + 8HH + (19 + 6W)H | 152 + 32HH + (76 + 24W)H +;; ---------------------------------------------------------------- +;; W=2,H=16 | 534 / 542 | 2136 / 2168 +;; W=4,H=32 | 1430 / 1438 | 5720 / 5752 +;; ---------------------------------------------------------------- +;; Asm saving | -16 | -64 +;; ---------------------------------------------------------------- +;; (end code) +;; W = *width* in bytes, H = *height* in bytes, HH = integer((*H*-1)/8) +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + + ld a, c ;; [1] A = sprite width + ld (restore_width), a ;; [4] Modify sprite with in the code for the loop + + sub c ;; [1] | A = c - c - c = -c + sub c ;; [1] | A contains negative width + ld (neg_width), a ;; [4] Modify negative sprite width in the calculation code + + ld a, b ;; [1] A = sprite height + +next_line: +restore_width=.+1 + ld bc, #0x0000 ;; [3] 0000 is a placeholder for the width of a sprite line + ldir ;; [6*W-1] Copy one complete sprite line + + dec a ;; [1] 1 less sprite line to end + ret z ;; [2/4] If no lines left, return + + ;; Make HL Point to next line start +neg_width=.+1 + ld bc, #0x0700 ;; [3] 0700 will be modified to be 07xx, with xx being negative width of the sprite + add hl, bc ;; [3] HL += 0x800 - sprite width + + ;; Check for memory boundaries + ld b, a ;; [1] Save the value of A into B (we need it for next loop iteration) + ld a, h ;; [1] A=H (to test bits 12,13 and 14 of the new video memory address) + and #0x38 ;; [2] We get the 3 bits (12,13 and 14) to test if we have crossed 8-line character boundary + ld a, b ;; [1] Restore A value (previously saved into B) + jr nz, next_line ;; [2/3] If bits 12,13 and 14 are 0, we are at the first line of a character + ;; .... which means we have crossed character boundaries and memory address will + ;; .... be incorrect. Else, we have not, so we can safely proceed to next_line + +_8line_character_boundary_crossed: + ;; Our address has moved out of the 16K memory bank of video memory. As memory addresses + ;; are 16-bits long (4 16K banks), in order to make it cycle to the start of the 16K bank + ;; we were located, we need to "jump" over the other 3 banks, which means adding 48K (0xC000). + ;; As we also want to jump to the next character line, which is 0x50 bytes away, we need + ;; to add 0xC050 in total. + ld bc, #0xC050 ;; [3] Value to be added to make HL point to next pixel line in video memory + add hl, bc ;; [3] HL += 0xC050 + jr next_line ;; [3] Continue with next pixel line + diff --git a/cpctelera/src/video/cpct_getScreenToSprite_asmbindings.s b/cpctelera/src/video/cpct_getScreenToSprite_asmbindings.s index 46f4be8df..71603285d 100644 --- a/cpctelera/src/video/cpct_getScreenToSprite_asmbindings.s +++ b/cpctelera/src/video/cpct_getScreenToSprite_asmbindings.s @@ -1,7 +1,7 @@ ;;-----------------------------LICENSE NOTICE------------------------------------ ;; This file is part of CPCtelera: An Amstrad CPC Game Engine -;; Copyright (C) 2017 Arnaud Bouche -;; Copyright (C) 2015 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) +;; Copyright (C) 2018 Arnaud Bouche +;; Copyright (C) 2018 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) ;; ;; This program is free software: you can redistribute it and/or modify ;; it under the terms of the GNU Lesser General Public License as published by @@ -18,9 +18,6 @@ ;;------------------------------------------------------------------------------- .module cpct_sprites -;; Macros for easy use of undocumented opcodes -.include "../macros/cpct_undocumentedOpcodes.h.s" - ;; ;; ASM bindings for <cpct_getScreenToSprite> ;; diff --git a/cpctelera/src/video/cpct_getScreenToSprite_cbindings.s b/cpctelera/src/video/cpct_getScreenToSprite_cbindings.s index e6b778f3a..ed7efa8fa 100644 --- a/cpctelera/src/video/cpct_getScreenToSprite_cbindings.s +++ b/cpctelera/src/video/cpct_getScreenToSprite_cbindings.s @@ -1,7 +1,7 @@ ;;-----------------------------LICENSE NOTICE------------------------------------ ;; This file is part of CPCtelera: An Amstrad CPC Game Engine -;; Copyright (C) 2017 Arnaud Bouche -;; Copyright (C) 2015 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) +;; Copyright (C) 2018 Arnaud Bouche +;; Copyright (C) 2018 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) ;; ;; This program is free software: you can redistribute it and/or modify ;; it under the terms of the GNU Lesser General Public License as published by @@ -18,9 +18,6 @@ ;;------------------------------------------------------------------------------- .module cpct_sprites -;; Macros for easy use of undocumented opcodes -.include "../macros/cpct_undocumentedOpcodes.h.s" - ;; ;; C bindings for <cpct_getScreenToSprite> ;; @@ -29,8 +26,8 @@ _cpct_getScreenToSprite:: ;; GET Parameters from the stack pop af ;; [3] AF = Return Address - pop de ;; [3] DE = Source Screen Address (Video memory location) - pop hl ;; [3] HL = Destination Sprite Address (Sprite data array) + pop hl ;; [3] HL = Source Screen Address (Video memory location) + pop de ;; [3] DE = Destination Sprite Address (Sprite data array) pop bc ;; [3] BC = Height/Width (B = Height, C = Width) push af ;; [4] Put returning address in the stack again From c71041e8ac8c3644216dd3f8e2c515cad8c005de Mon Sep 17 00:00:00 2001 From: ronaldo <ronaldo@cheesetea.com> Date: Sat, 20 Jan 2018 18:14:54 +0100 Subject: [PATCH 18/31] Moved getScreenToSprite to sprites/screenToSprite --- .../cpct_getScreenToSprite.asm | 0 .../cpct_getScreenToSprite_asmbindings.s | 0 .../cpct_getScreenToSprite_cbindings.s | 0 .../sprites/screenToSprite/screenToSprite.h | 36 +++++++++++++++++++ cpctelera/src/sprites/sprites.h | 3 +- cpctelera/src/video/videomode.h | 5 +-- 6 files changed, 39 insertions(+), 5 deletions(-) rename cpctelera/src/{video => sprites/screenToSprite}/cpct_getScreenToSprite.asm (100%) rename cpctelera/src/{video => sprites/screenToSprite}/cpct_getScreenToSprite_asmbindings.s (100%) rename cpctelera/src/{video => sprites/screenToSprite}/cpct_getScreenToSprite_cbindings.s (100%) create mode 100644 cpctelera/src/sprites/screenToSprite/screenToSprite.h diff --git a/cpctelera/src/video/cpct_getScreenToSprite.asm b/cpctelera/src/sprites/screenToSprite/cpct_getScreenToSprite.asm similarity index 100% rename from cpctelera/src/video/cpct_getScreenToSprite.asm rename to cpctelera/src/sprites/screenToSprite/cpct_getScreenToSprite.asm diff --git a/cpctelera/src/video/cpct_getScreenToSprite_asmbindings.s b/cpctelera/src/sprites/screenToSprite/cpct_getScreenToSprite_asmbindings.s similarity index 100% rename from cpctelera/src/video/cpct_getScreenToSprite_asmbindings.s rename to cpctelera/src/sprites/screenToSprite/cpct_getScreenToSprite_asmbindings.s diff --git a/cpctelera/src/video/cpct_getScreenToSprite_cbindings.s b/cpctelera/src/sprites/screenToSprite/cpct_getScreenToSprite_cbindings.s similarity index 100% rename from cpctelera/src/video/cpct_getScreenToSprite_cbindings.s rename to cpctelera/src/sprites/screenToSprite/cpct_getScreenToSprite_cbindings.s diff --git a/cpctelera/src/sprites/screenToSprite/screenToSprite.h b/cpctelera/src/sprites/screenToSprite/screenToSprite.h new file mode 100644 index 000000000..4b5646fc7 --- /dev/null +++ b/cpctelera/src/sprites/screenToSprite/screenToSprite.h @@ -0,0 +1,36 @@ +//-----------------------------LICENSE NOTICE------------------------------------ +// This file is part of CPCtelera: An Amstrad CPC Game Engine +// Copyright (C) 2018 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) +// Copyright (C) 2018 Arnaud Bouche +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +//------------------------------------------------------------------------------- + +//##################################################################### +//### MODULE: Sprites +//### SUBMODULE: Screen To Sprite +//##################################################################### +//### This module contains specialized functions to read video memory +//### and copy it to linear arrays (sprites) in order to be used +//### later on as normal sprites. +//##################################################################### +// + +#ifndef CPCT_SCREEN2SPRITE_H +#define CPCT_SCREEN2SPRITE_H + +// Capture Video Memory area to buffer +extern void cpct_getScreenToSprite(u8* memory, u8* sprite, u8 width, u8 height) __z88dk_callee; + +#endif \ No newline at end of file diff --git a/cpctelera/src/sprites/sprites.h b/cpctelera/src/sprites/sprites.h index 45e3ec054..b53ab77fa 100644 --- a/cpctelera/src/sprites/sprites.h +++ b/cpctelera/src/sprites/sprites.h @@ -1,6 +1,6 @@ //-----------------------------LICENSE NOTICE------------------------------------ // This file is part of CPCtelera: An Amstrad CPC Game Engine -// Copyright (C) 2014-2017 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) +// Copyright (C) 2018 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Lesser General Public License as published by @@ -31,6 +31,7 @@ #include "sprite_types.h" #include "transparency_table_macros.h" #include "drawToSpriteBuffer/drawToSpriteBuffer.h" +#include "screenToSprite/screenToSprite.h" #include "drawTile/drawTile.h" #include "flipping/flipping.h" #include "blending/blending.h" diff --git a/cpctelera/src/video/videomode.h b/cpctelera/src/video/videomode.h index dc53c6057..771913e8e 100644 --- a/cpctelera/src/video/videomode.h +++ b/cpctelera/src/video/videomode.h @@ -1,6 +1,6 @@ //-----------------------------LICENSE NOTICE------------------------------------ // This file is part of CPCtelera: An Amstrad CPC Game Engine -// Copyright (C) 2014-2016 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) +// Copyright (C) 2018 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Lesser General Public License as published by @@ -47,7 +47,4 @@ extern u8* cpct_getScreenPtr (void* screen_start, u8 x, u8 y) __z88dk_callee; // Change Screen Resolutions setting CRTC register values extern void cpct_setCRTCReg (u8 regnum, u8 newval) __z88dk_callee; -// Capture Video Memory area to buffer -extern void cpct_getScreenToSprite(u8* memory, u8* sprite, u8 width, u8 height) __z88dk_callee; - #endif From 03f1eb3400e902992a8ba8232e2fa82846c1b09b Mon Sep 17 00:00:00 2001 From: Arnaud <arnaud_bouche@hotmail.com> Date: Sat, 20 Jan 2018 19:48:25 +0100 Subject: [PATCH 19/31] Using spaces instead of tabs for indenting --- .../medium/colorReplace/src/declarations.h | 44 +- examples/medium/colorReplace/src/drawing.c | 510 +++++++++--------- examples/medium/colorReplace/src/drawing.h | 4 +- examples/medium/colorReplace/src/main.c | 58 +- .../medium/colorReplace/src/manageVideoMem.c | 6 +- .../medium/colorReplace/src/manageVideoMem.h | 4 +- 6 files changed, 313 insertions(+), 313 deletions(-) diff --git a/examples/medium/colorReplace/src/declarations.h b/examples/medium/colorReplace/src/declarations.h index 0c25f2044..939375d67 100644 --- a/examples/medium/colorReplace/src/declarations.h +++ b/examples/medium/colorReplace/src/declarations.h @@ -43,44 +43,44 @@ // Memory location definition enum { - VIDEO_MEM, - BUFFER_MEM, - NB_BUFFERS + VIDEO_MEM, + BUFFER_MEM, + NB_BUFFERS }; // Boolean definition -#define BOOL u8 -#define TRUE 1 -#define FALSE 0 +#define BOOL u8 +#define TRUE 1 +#define FALSE 0 // Double buffer location -#define SCREEN_BUFF 0x8000 -#define VMEM_SIZE 0x4000 +#define SCREEN_BUFF 0x8000 +#define VMEM_SIZE 0x4000 // Mask table location -#define MASK_TABLE_LOC (SCREEN_BUFF - 0x100) // 0x100 = Size of Mask Table +#define MASK_TABLE_LOC (SCREEN_BUFF - 0x100) // 0x100 = Size of Mask Table // New stack location -#define NEW_STACK_LOC (MASK_TABLE_LOC - 0x100) // 0x100 = Size of Stack +#define NEW_STACK_LOC (MASK_TABLE_LOC - 0x100) // 0x100 = Size of Stack // Screen size -#define SCREEN_CY 200 -#define SCREEN_CX 80 +#define SCREEN_CY 200 +#define SCREEN_CX 80 -#define VIEW_TOP 0 -#define VIEW_DOWN SCREEN_CY - 20 +#define VIEW_TOP 0 +#define VIEW_DOWN SCREEN_CY - 20 -#define POS_CLOUD_X 0 -#define POS_CLOUD_Y 20 +#define POS_CLOUD_X 0 +#define POS_CLOUD_Y 20 -#define NB_BALOONS 8 -#define BALOON_TRAIL 8 +#define NB_BALOONS 8 +#define BALOON_TRAIL 8 -#define BALOON_ACTIVE 1 -#define BALOON_INACTIVE 0 +#define BALOON_ACTIVE 1 +#define BALOON_INACTIVE 0 -#define NB_STARS 10 -#define NB_COLORS_STAR 7 +#define NB_STARS 10 +#define NB_COLORS_STAR 7 ///////////////////////////////////////////////////////////////////////////////// // Mask Table Definition for Mode 0 diff --git a/examples/medium/colorReplace/src/drawing.c b/examples/medium/colorReplace/src/drawing.c index 7a6bfc72b..414450594 100644 --- a/examples/medium/colorReplace/src/drawing.c +++ b/examples/medium/colorReplace/src/drawing.c @@ -1,8 +1,8 @@ //-----------------------------LICENSE NOTICE------------------------------------ // This file is part of CPCtelera: An Amstrad CPC Game Engine -// Copyright (C) 2017 Bouche Arnaud -// Copyright (C) 2017 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) +// Copyright (C) 2018 Bouche Arnaud (@Arnaud6128) +// Copyright (C) 2018 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Lesser General Public License as published by @@ -22,104 +22,104 @@ ///////////////////////////////////////////////////////////////////////////////// // GLOBAL VARIABLES -u8 gSpriteColorized[G_BALOON_W*G_BALOON_H]; // Array for sprite to color -u8 gBackGroundColor; // Background color -u8 gBaloonColor; // Current color baloon -u8 gPosCloud; // Position of cloude +u8 gSpriteColorized[G_BALOON_W*G_BALOON_H]; // Array for sprite to color +u8 gBackGroundColor; // Background color +u8 gBaloonColor; // Current color baloon +u8 gPosCloud; // Position of cloude ///////////////////////////////////////////////////////////////////////////////// // STRUCTURES DEFINITION -typedef struct TBaloon // Baloon structure +typedef struct TBaloon // Baloon structure { - i16 posY; // Absolute Baloon PosY (can be outside screen) - u8 posX; // Absolute Baloon PosX - - u8 drawPosY; // In screen Baloon PosY - u8 drawCY; // In screen Baloon Height - - u8 speed; // Baloon speed - u8 color; // Baloon color drawn - - u8 status; // Baloon status ACTIVE / INACTIVE + i16 posY; // Absolute Baloon PosY (can be outside screen) + u8 posX; // Absolute Baloon PosX + + u8 drawPosY; // In screen Baloon PosY + u8 drawCY; // In screen Baloon Height + + u8 speed; // Baloon speed + u8 color; // Baloon color drawn + + u8 status; // Baloon status ACTIVE / INACTIVE } SBaloon; -typedef struct TBaloons // All baloons structure +typedef struct TBaloons // All baloons structure { - u8 nb; // Nb baloons in screen - SBaloon baloons[NB_BALOONS]; // Array of baloon + u8 nb; // Nb baloons in screen + SBaloon baloons[NB_BALOONS]; // Array of baloon } SBaloons; -SBaloons gBaloons; // Baloons to draw +SBaloons gBaloons; // Baloons to draw -typedef struct TStar // Lighting star structure +typedef struct TStar // Lighting star structure { - u8 posX; // Screen PosX - u8 posY; // Screen PosY + u8 posX; // Screen PosX + u8 posY; // Screen PosY - u8 color; // Star color drawn + u8 color; // Star color drawn } SStar; -typedef struct TStars // All stars structure +typedef struct TStars // All stars structure { - SStar stars[NB_STARS]; // Array of stars + SStar stars[NB_STARS]; // Array of stars } SStars; -SStars gStars; // Stars to draw +SStars gStars; // Stars to draw /////////////////////////////////////////////////////// -/// GET RANDOM FROM 0 TO MAX-1 +/// GET RANDOM FROM 0 TO MAX-1 /// u8 GetRand(u8 max) { - return cpct_rand()%max; + return cpct_rand()%max; } /////////////////////////////////////////////////////// -/// CHANGE TWO COLORS OF BALOON SPRITE +/// CHANGE TWO COLORS OF BALOON SPRITE /// void ColorSprite(u8 color) { - // Replace the two colors 1 and 2 of sprite baloon - cpct_spriteColorizeM0(g_baloon, gSpriteColorized, G_BALOON_W, G_BALOON_H, 1, color); // Colors are consecutives - cpct_spriteColorizeM0(gSpriteColorized, gSpriteColorized, G_BALOON_W, G_BALOON_H, 2, color + 1); + // Replace the two colors 1 and 2 of sprite baloon + cpct_spriteColorizeM0(g_baloon, gSpriteColorized, G_BALOON_W, G_BALOON_H, 1, color); // Colors are consecutives + cpct_spriteColorizeM0(gSpriteColorized, gSpriteColorized, G_BALOON_W, G_BALOON_H, 2, color + 1); } /////////////////////////////////////////////////////// -/// CLEAR BALOON BACKGROUND +/// CLEAR BALOON BACKGROUND /// void ClearBaloon(SBaloon* baloon) { - // If baloon in visible part of view - if (baloon->drawPosY < VIEW_DOWN) - { - u8* pvmem; - - // Compute size to be filled with background color - u8 clearCY = baloon->drawCY + BALOON_TRAIL; - - // Compute position to clear - u8 posDownClearY = baloon->drawPosY + clearCY; - if (posDownClearY > VIEW_DOWN) - clearCY = VIEW_DOWN - baloon->drawPosY; - - // Draw the box with background color to clear - pvmem = GetBackBufferPtr(baloon->posX, baloon->drawPosY); - cpct_drawSolidBox(pvmem, gBackGroundColor, G_BALOON_W, clearCY); - } + // If baloon in visible part of view + if (baloon->drawPosY < VIEW_DOWN) + { + u8* pvmem; + + // Compute size to be filled with background color + u8 clearCY = baloon->drawCY + BALOON_TRAIL; + + // Compute position to clear + u8 posDownClearY = baloon->drawPosY + clearCY; + if (posDownClearY > VIEW_DOWN) + clearCY = VIEW_DOWN - baloon->drawPosY; + + // Draw the box with background color to clear + pvmem = GetBackBufferPtr(baloon->posX, baloon->drawPosY); + cpct_drawSolidBox(pvmem, gBackGroundColor, G_BALOON_W, clearCY); + } } /////////////////////////////////////////////////////// -/// DELETE BALOON +/// DELETE BALOON /// void DeleteBaloons(SBaloon* baloons, SBaloon* baloonToDel, u8* nb) { - // Get last baloon in array - // Decrement number of remaining baloons in array - const SBaloon* lastBaloon = &baloons[--*nb]; - - // Replace baloon to be deleted with last baloon (if they are not the same) - if (baloonToDel != lastBaloon) - cpct_memcpy(baloonToDel, lastBaloon, sizeof(SBaloon)); + // Get last baloon in array + // Decrement number of remaining baloons in array + const SBaloon* lastBaloon = &baloons[--*nb]; + + // Replace baloon to be deleted with last baloon (if they are not the same) + if (baloonToDel != lastBaloon) + cpct_memcpy(baloonToDel, lastBaloon, sizeof(SBaloon)); } /////////////////////////////////////////////////////// @@ -127,85 +127,85 @@ void DeleteBaloons(SBaloon* baloons, SBaloon* baloonToDel, u8* nb) /// void UpdateBaloons() { - SBaloon* itBaloon = gBaloons.baloons; - u8 i; - - // Test if we can add a new baloon - if (gBaloons.nb < NB_BALOONS) - { - // Add new baloon at end of array - // Increment number of baloons in array - SBaloon* newBaloon = &gBaloons.baloons[gBaloons.nb++]; - - // Get random positions X and Y - newBaloon->posX = GetRand(SCREEN_CX - G_BALOON_W); - newBaloon->posY = SCREEN_CY - GetRand(40); - - // Get random speed - newBaloon->speed = GetRand(3) + 2; - - // Get circular next color 2 by 2 until 12 - gBaloonColor = (gBaloonColor + 2) % 12; - newBaloon->color = gBaloonColor + 1; - - // Set baloon ACTIVE - newBaloon->status = BALOON_ACTIVE; - } - - // Update all baloons - for (i = 0; i < gBaloons.nb; i++) - { - // If baloon active move and draw it - if (itBaloon->status == BALOON_ACTIVE) - { - // Test if whole baloon outside view - if (itBaloon->posY + G_BALOON_H < VIEW_TOP) - { - // Set baloon inactive - itBaloon->status = BALOON_INACTIVE; - // Clear baloon background - ClearBaloon(itBaloon); - } - else - { - // Move baloon to up according its speed - i16 posY = itBaloon->posY - itBaloon->speed; - itBaloon->posY = posY; + SBaloon* itBaloon = gBaloons.baloons; + u8 i; + + // Test if we can add a new baloon + if (gBaloons.nb < NB_BALOONS) + { + // Add new baloon at end of array + // Increment number of baloons in array + SBaloon* newBaloon = &gBaloons.baloons[gBaloons.nb++]; + + // Get random positions X and Y + newBaloon->posX = GetRand(SCREEN_CX - G_BALOON_W); + newBaloon->posY = SCREEN_CY - GetRand(40); + + // Get random speed + newBaloon->speed = GetRand(3) + 2; + + // Get circular next color 2 by 2 until 12 + gBaloonColor = (gBaloonColor + 2) % 12; + newBaloon->color = gBaloonColor + 1; + + // Set baloon ACTIVE + newBaloon->status = BALOON_ACTIVE; + } + + // Update all baloons + for (i = 0; i < gBaloons.nb; i++) + { + // If baloon active move and draw it + if (itBaloon->status == BALOON_ACTIVE) + { + // Test if whole baloon outside view + if (itBaloon->posY + G_BALOON_H < VIEW_TOP) + { + // Set baloon inactive + itBaloon->status = BALOON_INACTIVE; + // Clear baloon background + ClearBaloon(itBaloon); + } + else + { + // Move baloon to up according its speed + i16 posY = itBaloon->posY - itBaloon->speed; + itBaloon->posY = posY; - // Baloon outside view by top - if (posY < VIEW_TOP) - { - itBaloon->drawPosY = 0; - itBaloon->drawCY = G_BALOON_H + posY; - } - else - // Baloon outside view by down - if (posY + G_BALOON_H > VIEW_DOWN) - { - itBaloon->drawPosY = posY; - itBaloon->drawCY = VIEW_DOWN - posY; - } - // Baloon all in view - else - { - itBaloon->drawPosY = posY; - itBaloon->drawCY = G_BALOON_H; - } - } - } - // If inactive delete baloon - else - { - // Clear baloon background - ClearBaloon(itBaloon); - - // Delete baloon from list - DeleteBaloons(gBaloons.baloons, itBaloon, &gBaloons.nb); - } - - // Get next baloon pointer - itBaloon++; - } + // Baloon outside view by top + if (posY < VIEW_TOP) + { + itBaloon->drawPosY = 0; + itBaloon->drawCY = G_BALOON_H + posY; + } + else + // Baloon outside view by down + if (posY + G_BALOON_H > VIEW_DOWN) + { + itBaloon->drawPosY = posY; + itBaloon->drawCY = VIEW_DOWN - posY; + } + // Baloon all in view + else + { + itBaloon->drawPosY = posY; + itBaloon->drawCY = G_BALOON_H; + } + } + } + // If inactive delete baloon + else + { + // Clear baloon background + ClearBaloon(itBaloon); + + // Delete baloon from list + DeleteBaloons(gBaloons.baloons, itBaloon, &gBaloons.nb); + } + + // Get next baloon pointer + itBaloon++; + } } /////////////////////////////////////////////////////// @@ -213,27 +213,27 @@ void UpdateBaloons() /// void DrawBaloon(SBaloon* baloon, const u8* spriteBaloon) { - i16 posY = baloon->posY; - - // If baloon in view - if (posY + G_BALOON_H > VIEW_TOP && posY < VIEW_DOWN) - { - // Get VMem pointer of current baloon position - u8* pvmem = GetBackBufferPtr(baloon->posX, baloon->drawPosY); - const u8* sprite = (u8*)spriteBaloon; - - // Baloon partialy outside view by top - if (posY < VIEW_TOP) - { - // Compute Y position - u8 y = -posY; - - // Compute sprite offset - sprite = (u8*)spriteBaloon + G_BALOON_W * y; - } - - cpct_drawSpriteMaskedAlignedTable(sprite, pvmem, G_BALOON_W, baloon->drawCY, gMaskTable); - } + i16 posY = baloon->posY; + + // If baloon in view + if (posY + G_BALOON_H > VIEW_TOP && posY < VIEW_DOWN) + { + // Get VMem pointer of current baloon position + u8* pvmem = GetBackBufferPtr(baloon->posX, baloon->drawPosY); + const u8* sprite = (u8*)spriteBaloon; + + // Baloon partialy outside view by top + if (posY < VIEW_TOP) + { + // Compute Y position + u8 y = -posY; + + // Compute sprite offset + sprite = (u8*)spriteBaloon + G_BALOON_W * y; + } + + cpct_drawSpriteMaskedAlignedTable(sprite, pvmem, G_BALOON_W, baloon->drawCY, gMaskTable); + } } /////////////////////////////////////////////////////// @@ -241,42 +241,42 @@ void DrawBaloon(SBaloon* baloon, const u8* spriteBaloon) /// void DrawStars() { - // Static stars color - const static u8 sColorStar[NB_COLORS_STAR] = { 2, 4, 7, 8, 10, 11, 12 }; - static u8 color = 0; - - u8 i; - for (i = 0; i < NB_STARS; i++) - { - // Get video pointer of each star to be drawn - u8* pvmem = GetBackBufferPtr(gStars.stars[i].posX, gStars.stars[i].posY); - u8 color = gStars.stars[i].color++; - - // Use different drawing color methods - if (i < NB_STARS/3) - { - // Color and draw masked sprite in video memory - cpct_drawSpriteMaskedColorizeM0(g_star_trans, pvmem, G_STAR_TRANS_W, G_STAR_TRANS_H, 15, sColorStar[color]); - } - else if (i > NB_STARS/3 && i < 2*NB_STARS/3) - { - // Color and draw masked aligned sprite in video memory - cpct_drawSpriteMaskedAlignedColorizeM0(g_square, pvmem, G_SQUARE_W, G_SQUARE_H, 15, sColorStar[color], gMaskTable); - } - else - { - // Color and copy masked sprite in temporary array - u8 circleColor[G_CIRCLE_TRANS_W * G_CIRCLE_TRANS_H * 2]; - cpct_spriteMaskedColorizeM0(g_circle_trans, circleColor, G_CIRCLE_TRANS_W, G_CIRCLE_TRANS_H, 15, sColorStar[color]); - - // Draw masked Sprite from temporary array - cpct_drawSpriteMasked(circleColor, pvmem, G_CIRCLE_TRANS_W, G_CIRCLE_TRANS_H); - } - - // If all colors palette used restart from 0 - if (color == NB_COLORS_STAR - 1) - gStars.stars[i].color = 0; - } + // Static stars color + const static u8 sColorStar[NB_COLORS_STAR] = { 2, 4, 7, 8, 10, 11, 12 }; + static u8 color = 0; + + u8 i; + for (i = 0; i < NB_STARS; i++) + { + // Get video pointer of each star to be drawn + u8* pvmem = GetBackBufferPtr(gStars.stars[i].posX, gStars.stars[i].posY); + u8 color = gStars.stars[i].color++; + + // Use different drawing color methods + if (i < NB_STARS/3) + { + // Color and draw masked sprite in video memory + cpct_drawSpriteMaskedColorizeM0(g_star_trans, pvmem, G_STAR_TRANS_W, G_STAR_TRANS_H, 15, sColorStar[color]); + } + else if (i > NB_STARS/3 && i < 2*NB_STARS/3) + { + // Color and draw masked aligned sprite in video memory + cpct_drawSpriteMaskedAlignedColorizeM0(g_square, pvmem, G_SQUARE_W, G_SQUARE_H, 15, sColorStar[color], gMaskTable); + } + else + { + // Color and copy masked sprite in temporary array + u8 circleColor[G_CIRCLE_TRANS_W * G_CIRCLE_TRANS_H * 2]; + cpct_spriteMaskedColorizeM0(g_circle_trans, circleColor, G_CIRCLE_TRANS_W, G_CIRCLE_TRANS_H, 15, sColorStar[color]); + + // Draw masked Sprite from temporary array + cpct_drawSpriteMasked(circleColor, pvmem, G_CIRCLE_TRANS_W, G_CIRCLE_TRANS_H); + } + + // If all colors palette used restart from 0 + if (color == NB_COLORS_STAR - 1) + gStars.stars[i].color = 0; + } } /////////////////////////////////////////////////////// @@ -284,9 +284,9 @@ void DrawStars() /// void DrawCloud() { - // Draw cloud at fixed place - u8* pvmem = GetBackBufferPtr(0, POS_CLOUD_Y); - cpct_drawSprite(g_cloud, pvmem, G_CLOUD_W, G_CLOUD_H); + // Draw cloud at fixed place + u8* pvmem = GetBackBufferPtr(0, POS_CLOUD_Y); + cpct_drawSprite(g_cloud, pvmem, G_CLOUD_W, G_CLOUD_H); } /////////////////////////////////////////////////////// @@ -294,35 +294,35 @@ void DrawCloud() /// void DrawSceneBaloons() { - u8 i; - - // Clear background for all baloons - SBaloon* itBaloon = gBaloons.baloons; // Get first baloon pointer - for (i = 0; i < gBaloons.nb; i++) - { - ClearBaloon(itBaloon); - itBaloon++; - } - - // Draw sprite cloud - DrawCloud(); - - // Draw all baloons - itBaloon = gBaloons.baloons; // Get first baloon pointer - for (i = 0; i < gBaloons.nb; i++) - { - const u8* sprite = g_baloon; // Default baloon sprite (blue) + u8 i; + + // Clear background for all baloons + SBaloon* itBaloon = gBaloons.baloons; // Get first baloon pointer + for (i = 0; i < gBaloons.nb; i++) + { + ClearBaloon(itBaloon); + itBaloon++; + } + + // Draw sprite cloud + DrawCloud(); + + // Draw all baloons + itBaloon = gBaloons.baloons; // Get first baloon pointer + for (i = 0; i < gBaloons.nb; i++) + { + const u8* sprite = g_baloon; // Default baloon sprite (blue) - // Test if sprite have colors to change - if (itBaloon->color > 1) // Color 0 (white) is transparent color - { - ColorSprite(itBaloon->color); // Change colors of ballon - sprite = gSpriteColorized; // Sprite to draw is colorized baloon - } - - DrawBaloon(itBaloon, sprite); // Draw baloon sprite - itBaloon++; // Get next baloon - } + // Test if sprite have colors to change + if (itBaloon->color > 1) // Color 0 (white) is transparent color + { + ColorSprite(itBaloon->color); // Change colors of ballon + sprite = gSpriteColorized; // Sprite to draw is colorized baloon + } + + DrawBaloon(itBaloon, sprite); // Draw baloon sprite + itBaloon++; // Get next baloon + } } /////////////////////////////////////////////////////// @@ -330,21 +330,21 @@ void DrawSceneBaloons() /// void DrawBackground() { - u8* pvmem; - - // Fill video buffer with background color - cpct_memset((u8*)SCREEN_BUFF, gBackGroundColor, VMEM_SIZE); - - // Draw left part of Roof - pvmem = GetBackBufferPtr(0, SCREEN_CY-G_ROOF_H); - cpct_drawSprite(g_roof, pvmem, G_ROOF_W, G_ROOF_H); - - // Draw right part of Roof - pvmem += G_ROOF_W; - cpct_drawSprite(g_roof, pvmem, G_ROOF_W, G_ROOF_H); - - // Copy Same background on both buffers - cpct_memcpy(CPCT_VMEM_START, (u8*)SCREEN_BUFF, VMEM_SIZE); + u8* pvmem; + + // Fill video buffer with background color + cpct_memset((u8*)SCREEN_BUFF, gBackGroundColor, VMEM_SIZE); + + // Draw left part of Roof + pvmem = GetBackBufferPtr(0, SCREEN_CY-G_ROOF_H); + cpct_drawSprite(g_roof, pvmem, G_ROOF_W, G_ROOF_H); + + // Draw right part of Roof + pvmem += G_ROOF_W; + cpct_drawSprite(g_roof, pvmem, G_ROOF_W, G_ROOF_H); + + // Copy Same background on both buffers + cpct_memcpy(CPCT_VMEM_START, (u8*)SCREEN_BUFF, VMEM_SIZE); } ///////////////////////////////////////////////////////////////////////////////// @@ -354,18 +354,18 @@ void DrawBackground() /// void InitializeDrawing() { - u8 dx = SCREEN_CX / NB_STARS; // Compute space between stars - - u8 i; - for (i = 0; i < NB_STARS; i++) - { - gStars.stars[i].posX = dx * i + 5; // Constant space beetween stars - gStars.stars[i].posY = GetRand(10) + 175; // Random Y position from 175 to 184 - gStars.stars[i].color = GetRand(NB_COLORS_STAR); // Random color from 0 to NB_COLORS_STAR-1 - } - - gBackGroundColor = cpct_px2byteM0(14, 14); // Get byte color of background for M0 - gBaloons.nb = 0; // No baloon to draw at start - - DrawBackground(); // Set background on both buffers + u8 dx = SCREEN_CX / NB_STARS; // Compute space between stars + + u8 i; + for (i = 0; i < NB_STARS; i++) + { + gStars.stars[i].posX = dx * i + 5; // Constant space beetween stars + gStars.stars[i].posY = GetRand(10) + 175; // Random Y position from 175 to 184 + gStars.stars[i].color = GetRand(NB_COLORS_STAR); // Random color from 0 to NB_COLORS_STAR-1 + } + + gBackGroundColor = cpct_px2byteM0(14, 14); // Get byte color of background for M0 + gBaloons.nb = 0; // No baloon to draw at start + + DrawBackground(); // Set background on both buffers } diff --git a/examples/medium/colorReplace/src/drawing.h b/examples/medium/colorReplace/src/drawing.h index ad41ea5e4..f4ad6f644 100644 --- a/examples/medium/colorReplace/src/drawing.h +++ b/examples/medium/colorReplace/src/drawing.h @@ -1,7 +1,7 @@ //-----------------------------LICENSE NOTICE------------------------------------ // This file is part of CPCtelera: An Amstrad CPC Game Engine -// Copyright (C) 2017 Bouche Arnaud -// Copyright (C) 2017 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) +// Copyright (C) 2018 Bouche Arnaud (@Arnaud6128) +// Copyright (C) 2018 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Lesser General Public License as published by diff --git a/examples/medium/colorReplace/src/main.c b/examples/medium/colorReplace/src/main.c index b405a67f7..19489081e 100644 --- a/examples/medium/colorReplace/src/main.c +++ b/examples/medium/colorReplace/src/main.c @@ -1,6 +1,6 @@ //-----------------------------LICENSE NOTICE------------------------------------ // This file is part of CPCtelera: An Amstrad CPC Game Engine -// Copyright (C) 2017 Arnaud BOUCHE +// Copyright (C) 2017 Arnaud BOUCHE (@Arnaud6128) // Copyright (C) 2017 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) // // This program is free software: you can redistribute it and/or modify @@ -31,15 +31,15 @@ cpctm_createTransparentMaskTable(gMaskTable, MASK_TABLE_LOC, M0, 0); // void Initialization() { - // We need to disable firmware in order to set the palette and - // to be able to use a second screen between 0x8000 and 0xBFFF - cpct_disableFirmware(); - cpct_setVideoMode(0); // Set mode 0 - cpct_setPalette(g_palette, 16); // Set the palette - cpct_setBorder(0x57); // Set the border color with Hardware color (Sky Blue) - - InitializeVideoMemoryBuffers(); // Initialize video buffers - InitializeDrawing(); // Initialize drawing elements + // We need to disable firmware in order to set the palette and + // to be able to use a second screen between 0x8000 and 0xBFFF + cpct_disableFirmware(); + cpct_setVideoMode(0); // Set mode 0 + cpct_setPalette(g_palette, 16); // Set the palette + cpct_setBorder(HW_SKY_BLUE); // Set the border color with Hardware color + + InitializeVideoMemoryBuffers(); // Initialize video buffers + InitializeDrawing(); // Initialize drawing elements } /////////////////////////////////////////////////////// @@ -47,23 +47,23 @@ void Initialization() /// void main(void) { - // Change stack location before any call. We will be using - // memory from 0x8000 to 0xBFFF as secondary buffer, so - // the stack must not be there or it will get overwritten - cpct_setStackLocation((u8*)NEW_STACK_LOC); - - // Initialize everything - Initialization(); - - // Main Loop - while (TRUE) - { - UpdateBaloons(); - DrawSceneBaloons(); - DrawStars(); - - // Flip buffers to display the present back buffer - // and stop displaying the current video memory - FlipBuffers(); - } + // Change stack location before any call. We will be using + // memory from 0x8000 to 0xBFFF as secondary buffer, so + // the stack must not be there or it will get overwritten + cpct_setStackLocation((u8*)NEW_STACK_LOC); + + // Initialize everything + Initialization(); + + // Main Loop + while (TRUE) + { + UpdateBaloons(); + DrawSceneBaloons(); + DrawStars(); + + // Flip buffers to display the present back buffer + // and stop displaying the current video memory + FlipBuffers(); + } } diff --git a/examples/medium/colorReplace/src/manageVideoMem.c b/examples/medium/colorReplace/src/manageVideoMem.c index 1314592cd..3a14b2d28 100644 --- a/examples/medium/colorReplace/src/manageVideoMem.c +++ b/examples/medium/colorReplace/src/manageVideoMem.c @@ -1,7 +1,7 @@ //-----------------------------LICENSE NOTICE------------------------------------ // This file is part of CPCtelera: An Amstrad CPC Game Engine -// Copyright (C) 2017 Bouche Arnaud -// Copyright (C) 2017 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) +// Copyright (C) 2018 Bouche Arnaud (@Arnaud6128) +// Copyright (C) 2018 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Lesser General Public License as published by @@ -22,7 +22,7 @@ ///////////////////////////////////////////////////////////////////////////////// // GLOBAL VARIABLES // -u8 gVMem; // Current video mem +u8 gVMem; // Current video mem ///////////////////////////////////////////////////////////////////////////////// // INITITALIZE VIDEO MEMORY BUFFERS diff --git a/examples/medium/colorReplace/src/manageVideoMem.h b/examples/medium/colorReplace/src/manageVideoMem.h index 7f3ee4ed4..b508f294b 100644 --- a/examples/medium/colorReplace/src/manageVideoMem.h +++ b/examples/medium/colorReplace/src/manageVideoMem.h @@ -1,7 +1,7 @@ //-----------------------------LICENSE NOTICE------------------------------------ // This file is part of CPCtelera: An Amstrad CPC Game Engine -// Copyright (C) 2017 Bouche Arnaud -// Copyright (C) 2017 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) +// Copyright (C) 2018 Bouche Arnaud (@Arnaud6128) +// Copyright (C) 2018 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Lesser General Public License as published by From 83a7d882bfe9b5281a050edf24b06d00f46f3a9d Mon Sep 17 00:00:00 2001 From: Arnaud <arnaud_bouche@hotmail.com> Date: Sat, 20 Jan 2018 20:04:12 +0100 Subject: [PATCH 20/31] Replace tabs with spaces in coloreplace asm --- .../M0/cpct_drawSpriteColorizeM0.asm | 126 +++++------ .../cpct_drawSpriteColorizeM0_asmbindings.s | 2 +- .../M0/cpct_drawSpriteColorizeM0_cbindings.s | 4 +- ...cpct_drawSpriteMaskedAlignedColorizeM0.asm | 144 ++++++------- ...priteMaskedAlignedColorizeM0_asmbindings.s | 2 +- ...wSpriteMaskedAlignedColorizeM0_cbindings.s | 2 +- .../M0/cpct_drawSpriteMaskedColorizeM0.asm | 136 ++++++------ ...t_drawSpriteMaskedColorizeM0_asmbindings.s | 4 +- ...pct_drawSpriteMaskedColorizeM0_cbindings.s | 4 +- .../colorReplace/M0/cpct_spriteColorizeM0.asm | 116 +++++------ .../M0/cpct_spriteColorizeM0_asmbindings.s | 4 +- .../M0/cpct_spriteColorizeM0_cbindings.s | 4 +- .../M0/cpct_spriteMaskedColorizeM0.asm | 120 +++++------ .../cpct_spriteMaskedColorizeM0_asmbindings.s | 4 +- .../cpct_spriteMaskedColorizeM0_cbindings.s | 4 +- .../M1/cpct_drawSpriteColorizeM1.asm | 174 ++++++++-------- .../cpct_drawSpriteColorizeM1_asmbindings.s | 4 +- .../M1/cpct_drawSpriteColorizeM1_cbindings.s | 4 +- ...cpct_drawSpriteMaskedAlignedColorizeM1.asm | 186 ++++++++--------- ...priteMaskedAlignedColorizeM1_asmbindings.s | 4 +- ...wSpriteMaskedAlignedColorizeM1_cbindings.s | 6 +- .../M1/cpct_drawSpriteMaskedColorizeM1.asm | 196 +++++++++--------- ...t_drawSpriteMaskedColorizeM1_asmbindings.s | 4 +- ...pct_drawSpriteMaskedColorizeM1_cbindings.s | 4 +- .../colorReplace/M1/cpct_spriteColorizeM1.asm | 168 +++++++-------- .../M1/cpct_spriteColorizeM1_asmbindings.s | 4 +- .../M1/cpct_spriteColorizeM1_cbindings.s | 4 +- .../M1/cpct_spriteMaskedColorizeM1.asm | 180 ++++++++-------- .../cpct_spriteMaskedColorizeM1_asmbindings.s | 4 +- .../cpct_spriteMaskedColorizeM1_cbindings.s | 4 +- 30 files changed, 811 insertions(+), 811 deletions(-) diff --git a/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteColorizeM0.asm b/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteColorizeM0.asm index 13d195147..a40ef9e87 100644 --- a/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteColorizeM0.asm +++ b/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteColorizeM0.asm @@ -1,7 +1,7 @@ ;;-----------------------------LICENSE NOTICE------------------------------------ ;; This file is part of CPCtelera: An Amstrad CPC Game Engine -;; Copyright (C) 2017 Arnaud Bouche (Arnaud6128) -;; Copyright (C) 2017 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) +;; Copyright (C) 2018 Arnaud Bouche (@Arnaud6128) +;; Copyright (C) 2018 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) ;; ;; This program is free software: you can redistribute it and/or modify ;; it under the terms of the GNU Lesser General Public License as published by @@ -104,86 +104,86 @@ ;; Macro to convert Pixel to xAxC xBxD format .macro convertPixel - ;; From cpct_px2byteM0 - ld bc, #dc_mode0_ct ;; [3] BC points to conversion table (dc_mode0_ct) - - ;; Compute BC += A - add c ;; [1] | C += A - ld c, a ;; [1] | - sub a ;; [1] A = 0 (preserving Carry Flag) - adc b ;; [1] | B += Carry - ld b, a ;; [1] | + ;; From cpct_px2byteM0 + ld bc, #dc_mode0_ct ;; [3] BC points to conversion table (dc_mode0_ct) + + ;; Compute BC += A + add c ;; [1] | C += A + ld c, a ;; [1] | + sub a ;; [1] A = 0 (preserving Carry Flag) + adc b ;; [1] | B += Carry + ld b, a ;; [1] | ;; A = *(BC + A) ld a, (bc) ;; [2] A = Value stored at the table pointed by BC .endm - ;; Convert newColor to pixel format (E) - ld a, h ;; [1] A = H new color index - convertPixel ;; [10] | Convert into A - ld e, a ;; [1] | E = A new color : xAxC xBxD + ;; Convert newColor to pixel format (E) + ld a, h ;; [1] A = H new color index + convertPixel ;; [10] | Convert into A + ld e, a ;; [1] | E = A new color : xAxC xBxD - ;; Convert oldColor to pixel format (D) - ld a, l ;; [1] A = L old color index - convertPixel ;; [10] | Convert into A - ld d, a ;; [1] | D = A old color : xAxC xBxD - - ld c, #0x55 ;; [2] C = Mask to get pixel A : xAxC xBxD - - exx ;; [1] Switch to Alternate registers - - ld__ixl_c ;; [1] IXL = C (Width) - ld c, b ;; [1] C = B (Height) - -convertLoop: - ld (startLine), de ;; [6] Store DE start line (DestMem) - ld__b_ixl ;; [2] B = IXL (Sprite Width) + ;; Convert oldColor to pixel format (D) + ld a, l ;; [1] A = L old color index + convertPixel ;; [10] | Convert into A + ld d, a ;; [1] | D = A old color : xAxC xBxD + + ld c, #0x55 ;; [2] C = Mask to get pixel A : xAxC xBxD + + exx ;; [1] Switch to Alternate registers + + ld__ixl_c ;; [1] IXL = C (Width) + ld c, b ;; [1] C = B (Height) + +convertLoop: + ld (startLine), de ;; [6] Store DE start line (DestMem) + ld__b_ixl ;; [2] B = IXL (Sprite Width) lineLoop: - ld a, (hl) ;; [2] A = (HL) current Byte of sprite + ld a, (hl) ;; [2] A = (HL) current Byte of sprite exx ;; [1] Switch to Default registers - - ld l, a ;; [1] L = A current Byte of sprite : ABAB ABAB - and c ;; [2] A |= C (C = 0x55) : xBxB xBxB - - cp d ;; [1] Test if pixel (A) is the old colour to be replaced (D) - jr nz, readPixelA ;; [2/3] If not equal go to next pixel + + ld l, a ;; [1] L = A current Byte of sprite : ABAB ABAB + and c ;; [2] A |= C (C = 0x55) : xBxB xBxB + + cp d ;; [1] Test if pixel (A) is the old colour to be replaced (D) + jr nz, readPixelA ;; [2/3] If not equal go to next pixel ld a, e ;; [1] else A = new colour to set (E) ;; Pixel Mode 0 = ABAB ABAB readPixelA: - ld h, a ;; [1] H = A (current colorized sprite) : xBxB xBxB - ld a, l ;; [1] L = A current Byte of sprite : ABAB ABAB - rrca ;; [1] A (current byte of sprite) >> 1 : ABAB ABAB -> xABA BABA - and c ;; [2] A |= Mask (0x55) : xAxA xAxA - - cp d ;; [1] Test if pixel (A) is the old colour to be replaced (D) - jr nz, readPixelB ;; [2/3] If not equal go to next pixel + ld h, a ;; [1] H = A (current colorized sprite) : xBxB xBxB + ld a, l ;; [1] L = A current Byte of sprite : ABAB ABAB + rrca ;; [1] A (current byte of sprite) >> 1 : ABAB ABAB -> xABA BABA + and c ;; [2] A |= Mask (0x55) : xAxA xAxA + + cp d ;; [1] Test if pixel (A) is the old colour to be replaced (D) + jr nz, readPixelB ;; [2/3] If not equal go to next pixel ld a, e ;; [1] else A = new colour to set (E) - + readPixelB: - rlca ;; [1] A = xAxA xAxA << 1 : AxAx AxAx - or h ;; [1] A |= H (xBxB xBxB) : ABAB ABAB + rlca ;; [1] A = xAxA xAxA << 1 : AxAx AxAx + or h ;; [1] A |= H (xBxB xBxB) : ABAB ABAB - exx ;; [1] Switch to Alternate registers + exx ;; [1] Switch to Alternate registers drawByte: - ld (de), a ;; [2] Update current sprite byte with pixels - inc hl ;; [2] Next byte sprite source - inc de ;; [2] Next byte sprite colorized - djnz lineLoop ;; [3] Decrement B (Width) if B != 0 goto lineLoop - - dec c ;; [1] Decrement C (Height) - jr z, end ;; [2/3] If C == O goto end + ld (de), a ;; [2] Update current sprite byte with pixels + inc hl ;; [2] Next byte sprite source + inc de ;; [2] Next byte sprite colorized + djnz lineLoop ;; [3] Decrement B (Width) if B != 0 goto lineLoop + + dec c ;; [1] Decrement C (Height) + jr z, end ;; [2/3] If C == O goto end startLine = .+1 ;; Placeholder for the Start line adress - ld de, #0000 ;; [3] DE = Start Line + ld de, #0000 ;; [3] DE = Start Line ld a, d ;; [1] Start of next pixel line normally is 0x0800 bytes away. add #0x08 ;; [2] so we add it to DE (just by adding 0x08 to D) ld d, a ;; [1] - and #0x38 ;; [2] We check if we have crossed memory boundary (every 8 pixel lines).. - + and #0x38 ;; [2] We check if we have crossed memory boundary (every 8 pixel lines).. + jr nz, convertLoop ;; [2/3] .. by checking the 4 bits that identify present memory line. ;; .... If 0, we have crossed boundaries @@ -194,10 +194,10 @@ dms_sprite_8bit_boundary_crossed: ld a, d ;; [1] -- which effectively is the same as moving it 1 bank backwards and then adc #0xC0 ;; [2] -- 50 bytes forwards (which is what we want to move it to the next pixel line) ld d, a ;; [1] -- Calculations are made with 8 bit maths as it is faster than other alternatives here - - jr convertLoop ;; [3] Jump to continue with next pixel line + + jr convertLoop ;; [3] Jump to continue with next pixel line end: - ;; Return is included in bindings - - + ;; Return is included in bindings + + diff --git a/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteColorizeM0_asmbindings.s b/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteColorizeM0_asmbindings.s index 7dd12e5e0..073609b70 100644 --- a/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteColorizeM0_asmbindings.s +++ b/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteColorizeM0_asmbindings.s @@ -1,6 +1,6 @@ ;;-----------------------------LICENSE NOTICE------------------------------------ ;; This file is part of CPCtelera: An Amstrad CPC Game Engine -;; Copyright (C) 2017 Arnaud Bouche (Arnaud6128) +;; Copyright (C) 2017 Arnaud Bouche (@Arnaud6128) ;; Copyright (C) 2017 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) ;; ;; This program is free software: you can redistribute it and/or modify diff --git a/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteColorizeM0_cbindings.s b/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteColorizeM0_cbindings.s index 063414615..f4ad4b2f5 100644 --- a/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteColorizeM0_cbindings.s +++ b/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteColorizeM0_cbindings.s @@ -1,6 +1,6 @@ ;;-----------------------------LICENSE NOTICE------------------------------------ ;; This file is part of CPCtelera: An Amstrad CPC Game Engine -;; Copyright (C) 2017 Arnaud Bouche (Arnaud6128) +;; Copyright (C) 2017 Arnaud Bouche (@Arnaud6128) ;; Copyright (C) 2017 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) ;; ;; This program is free software: you can redistribute it and/or modify @@ -40,7 +40,7 @@ _cpct_drawSpriteColorizeM0:: ex (sp), hl ;; [6] HL = (H = newColor, L = oldColor) ;; ... and leave Return Address at (SP) as we don't need to restore ;; ... stack status because callin convention is __z88dk_callee - + .include /cpct_drawSpriteColorizeM0.asm/ dms_restore_ix: diff --git a/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteMaskedAlignedColorizeM0.asm b/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteMaskedAlignedColorizeM0.asm index 21308854d..981c21ab2 100644 --- a/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteMaskedAlignedColorizeM0.asm +++ b/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteMaskedAlignedColorizeM0.asm @@ -1,7 +1,7 @@ ;;-----------------------------LICENSE NOTICE------------------------------------ ;; This file is part of CPCtelera: An Amstrad CPC Game Engine -;; Copyright (C) 2017 Arnaud Bouche (Arnaud6128) -;; Copyright (C) 2017 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) +;; Copyright (C) 2018 Arnaud Bouche (@Arnaud6128) +;; Copyright (C) 2018 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) ;; ;; This program is free software: you can redistribute it and/or modify ;; it under the terms of the GNU Lesser General Public License as published by @@ -106,95 +106,95 @@ ;; Macro to convert Pixel to xAxC xBxD format .macro convertPixel - ;; From cpct_px2byteM0 - ld bc, #dc_mode0_ct ;; [3] BC points to conversion table (dc_mode0_ct) - - ;; Compute BC += A - add c ;; [1] | C += A - ld c, a ;; [1] | - sub a ;; [1] A = 0 (preserving Carry Flag) - adc b ;; [1] | B += Carry - ld b, a ;; [1] | + ;; From cpct_px2byteM0 + ld bc, #dc_mode0_ct ;; [3] BC points to conversion table (dc_mode0_ct) + + ;; Compute BC += A + add c ;; [1] | C += A + ld c, a ;; [1] | + sub a ;; [1] A = 0 (preserving Carry Flag) + adc b ;; [1] | B += Carry + ld b, a ;; [1] | ;; A = *(BC + A) ld a, (bc) ;; [2] A = Value stored at the table pointed by BC .endm - ;; Convert newColor to pixel format (E) - ld a, h ;; [1] A = H new color index - convertPixel ;; [10] | Convert into A - ld e, a ;; [1] | E = A new color : xAxC xBxD + ;; Convert newColor to pixel format (E) + ld a, h ;; [1] A = H new color index + convertPixel ;; [10] | Convert into A + ld e, a ;; [1] | E = A new color : xAxC xBxD - ;; Convert oldColor to pixel format (D) - ld a, l ;; [1] A = L old color index - convertPixel ;; [10] | Convert into A - ld b, d - ld d, a ;; [1] | D = A old color : xAxC xBxD - - ld c, #0x55 ;; [2] C = Mask to get pixel A : xAxC xBxD - exx ;; [1] Switch to Alternate registers - - ld__ixl_c ;; [1] IXL = C (Width) - ld c, b ;; [1] C = B (Height) - -convertLoop: - push de ;; [4] Store DE start line (DestMem) - ld__b_ixl ;; [2] B = IXL (Sprite Width) + ;; Convert oldColor to pixel format (D) + ld a, l ;; [1] A = L old color index + convertPixel ;; [10] | Convert into A + ld b, d + ld d, a ;; [1] | D = A old color : xAxC xBxD + + ld c, #0x55 ;; [2] C = Mask to get pixel A : xAxC xBxD + exx ;; [1] Switch to Alternate registers + + ld__ixl_c ;; [1] IXL = C (Width) + ld c, b ;; [1] C = B (Height) + +convertLoop: + push de ;; [4] Store DE start line (DestMem) + ld__b_ixl ;; [2] B = IXL (Sprite Width) lineLoop: - ld a, (hl) ;; [2] A = (HL) current Byte of sprite + ld a, (hl) ;; [2] A = (HL) current Byte of sprite exx ;; [1] Switch to Default registers - - ld l, a ;; [1] L = A current Byte of sprite : ABAB ABAB - and c ;; [2] A |= C (C = 0x55) : xBxB xBxB - - cp d ;; [1] Test if pixel (A) is the old colour to be replaced (D) - jr nz, readPixelA ;; [2/3] If not equal go to next pixel + + ld l, a ;; [1] L = A current Byte of sprite : ABAB ABAB + and c ;; [2] A |= C (C = 0x55) : xBxB xBxB + + cp d ;; [1] Test if pixel (A) is the old colour to be replaced (D) + jr nz, readPixelA ;; [2/3] If not equal go to next pixel ld a, e ;; [1] else A = new colour to set (E) ;; Pixel Mode 0 = ABAB ABAB readPixelA: - ld h, a ;; [1] H = A (current colorized sprite) : xBxB xBxB - ld a, l ;; [1] L = A current Byte of sprite : ABAB ABAB - rrca ;; [1] A (current byte of sprite) >> 1 : ABAB ABAB -> xABA BABA - and c ;; [2] A |= Mask (0x55) : xAxA xAxA - - cp d ;; [1] Test if pixel (A) is the old colour to be replaced (D) - jr nz, readPixelB ;; [2/3] If not equal go to next pixel + ld h, a ;; [1] H = A (current colorized sprite) : xBxB xBxB + ld a, l ;; [1] L = A current Byte of sprite : ABAB ABAB + rrca ;; [1] A (current byte of sprite) >> 1 : ABAB ABAB -> xABA BABA + and c ;; [2] A |= Mask (0x55) : xAxA xAxA + + cp d ;; [1] Test if pixel (A) is the old colour to be replaced (D) + jr nz, readPixelB ;; [2/3] If not equal go to next pixel ld a, e ;; [1] else A = new colour to set (E) - + readPixelB: - rlca ;; [1] A = xAxA xAxA << 1 : AxAx AxAx - or h ;; [1] A |= H (xBxB xBxB) : ABAB ABAB + rlca ;; [1] A = xAxA xAxA << 1 : AxAx AxAx + or h ;; [1] A |= H (xBxB xBxB) : ABAB ABAB drawByte: ld h, b ;; [1] H = B (Masked table adress High Byte) - ld l, a ;; [1] Access mask table element (table must be 256-byte aligned) - exx ;; [1] Switch to Alternate registers - - ld a, (de) ;; [2] Get the value of the byte of the screen where we are going to draw - exx ;; [1] Switch to Default registers - - and (hl) ;; [2] Erase background part that is to be overwritten (Mask step 1) - or l ;; [1] Add up background and sprite information in one byte (Mask step 2) - exx ;; [1] Switch to Alternate registers - - ld (de), a ;; [2] Save modified background + sprite data information into memory + ld l, a ;; [1] Access mask table element (table must be 256-byte aligned) + exx ;; [1] Switch to Alternate registers + + ld a, (de) ;; [2] Get the value of the byte of the screen where we are going to draw + exx ;; [1] Switch to Default registers + + and (hl) ;; [2] Erase background part that is to be overwritten (Mask step 1) + or l ;; [1] Add up background and sprite information in one byte (Mask step 2) + exx ;; [1] Switch to Alternate registers + + ld (de), a ;; [2] Save modified background + sprite data information into memory - inc hl ;; [2] Next byte sprite source - inc de ;; [2] Next byte sprite colorized - djnz lineLoop ;; [3] Decrement B (Width) if B != 0 goto lineLoop - - dec c ;; [1] Decrement C (Height) - jr z, end ;; [2/3] If C == O goto end + inc hl ;; [2] Next byte sprite source + inc de ;; [2] Next byte sprite colorized + djnz lineLoop ;; [3] Decrement B (Width) if B != 0 goto lineLoop + + dec c ;; [1] Decrement C (Height) + jr z, end ;; [2/3] If C == O goto end - pop de ;; [3] Restore DE start line (DestMem) + pop de ;; [3] Restore DE start line (DestMem) ld a, d ;; [1] Start of next pixel line normally is 0x0800 bytes away. add #0x08 ;; [2] so we add it to DE (just by adding 0x08 to D) ld d, a ;; [1] - and #0x38 ;; [2] We check if we have crossed memory boundary (every 8 pixel lines).. - + and #0x38 ;; [2] We check if we have crossed memory boundary (every 8 pixel lines).. + jr nz, convertLoop ;; [2/3] .. by checking the 4 bits that identify present memory line. ;; .... If 0, we have crossed boundaries @@ -205,11 +205,11 @@ dms_sprite_8bit_boundary_crossed: ld a, d ;; [1] -- which effectively is the same as moving it 1 bank backwards and then adc #0xC0 ;; [2] -- 50 bytes forwards (which is what we want to move it to the next pixel line) ld d, a ;; [1] -- Calculations are made with 8 bit maths as it is faster than other alternatives here - - jr convertLoop ;; [3] Jump to continue with next pixel line + + jr convertLoop ;; [3] Jump to continue with next pixel line end: pop de ;; [3] Empty stack by getting last element (DestMem) - ;; Return is included in bindings - - + ;; Return is included in bindings + + diff --git a/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteMaskedAlignedColorizeM0_asmbindings.s b/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteMaskedAlignedColorizeM0_asmbindings.s index e5ea9de3f..f566e8fc5 100644 --- a/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteMaskedAlignedColorizeM0_asmbindings.s +++ b/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteMaskedAlignedColorizeM0_asmbindings.s @@ -1,6 +1,6 @@ ;;-----------------------------LICENSE NOTICE------------------------------------ ;; This file is part of CPCtelera: An Amstrad CPC Game Engine -;; Copyright (C) 2017 Arnaud Bouche (Arnaud6128) +;; Copyright (C) 2017 Arnaud Bouche (@Arnaud6128) ;; Copyright (C) 2017 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) ;; ;; This program is free software: you can redistribute it and/or modify diff --git a/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteMaskedAlignedColorizeM0_cbindings.s b/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteMaskedAlignedColorizeM0_cbindings.s index 6578e5ea5..f8953c60b 100644 --- a/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteMaskedAlignedColorizeM0_cbindings.s +++ b/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteMaskedAlignedColorizeM0_cbindings.s @@ -42,7 +42,7 @@ _cpct_drawSpriteMaskedAlignedColorizeM0:: ex (sp), hl ;; [6] HL = Table Mask address ;; ... and leave Return Address at (SP) as we don't need to restore ;; ... stack status because callin convention is __z88dk_callee - + ex de, hl ;; [1] HL <-> DE .include /cpct_drawSpriteMaskedAlignedColorizeM0.asm/ diff --git a/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteMaskedColorizeM0.asm b/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteMaskedColorizeM0.asm index eb9fd04e4..8f63f4c99 100644 --- a/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteMaskedColorizeM0.asm +++ b/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteMaskedColorizeM0.asm @@ -109,96 +109,96 @@ ;; Macro to convert Pixel to xAxC xBxD format .macro convertPixel - ;; From cpct_px2byteM0 - ld bc, #dc_mode0_ct ;; [3] BC points to conversion table (dc_mode0_ct) - - ;; Compute BC += A - add c ;; [1] | C += A - ld c, a ;; [1] | - sub a ;; [1] A = 0 (preserving Carry Flag) - adc b ;; [1] | B += Carry - ld b, a ;; [1] | + ;; From cpct_px2byteM0 + ld bc, #dc_mode0_ct ;; [3] BC points to conversion table (dc_mode0_ct) + + ;; Compute BC += A + add c ;; [1] | C += A + ld c, a ;; [1] | + sub a ;; [1] A = 0 (preserving Carry Flag) + adc b ;; [1] | B += Carry + ld b, a ;; [1] | ;; A = *(BC + A) ld a, (bc) ;; [2] A = Value stored at the table pointed by BC .endm - ;; Convert newColor to pixel format (E) - ld a, h ;; [1] A = H new color index - convertPixel ;; [10] | Convert into A - ld e, a ;; [1] | E = A new color : xAxC xBxD + ;; Convert newColor to pixel format (E) + ld a, h ;; [1] A = H new color index + convertPixel ;; [10] | Convert into A + ld e, a ;; [1] | E = A new color : xAxC xBxD - ;; Convert oldColor to pixel format (D) - ld a, l ;; [1] A = L old color index - convertPixel ;; [10] | Convert into A - ld d, a ;; [1] | D = A old color : xAxC xBxD - - ld c, #0x55 ;; [2] C = Mask to get pixel A : xAxC xBxD - - exx ;; [1] Switch to Alternate registers - - ld__ixl_c ;; [1] IXL = C (Width) - ld c, b ;; [1] C = B (Height) - -convertLoop: - ld (startLine), de ;; [6] Store DE start line (DestMem) - ld__b_ixl ;; [2] B = IXL (Sprite Width) + ;; Convert oldColor to pixel format (D) + ld a, l ;; [1] A = L old color index + convertPixel ;; [10] | Convert into A + ld d, a ;; [1] | D = A old color : xAxC xBxD + + ld c, #0x55 ;; [2] C = Mask to get pixel A : xAxC xBxD + + exx ;; [1] Switch to Alternate registers + + ld__ixl_c ;; [1] IXL = C (Width) + ld c, b ;; [1] C = B (Height) + +convertLoop: + ld (startLine), de ;; [6] Store DE start line (DestMem) + ld__b_ixl ;; [2] B = IXL (Sprite Width) lineLoop: - inc hl ;; [2] Next byte sprite Color source - ld a, (hl) ;; [2] A = (HL) current Byte of sprite Color - dec hl ;; [2] Previous byte sprite Mask source - + inc hl ;; [2] Next byte sprite Color source + ld a, (hl) ;; [2] A = (HL) current Byte of sprite Color + dec hl ;; [2] Previous byte sprite Mask source + exx ;; [1] Switch to Default registers - - ld l, a ;; [1] L = A current Byte of sprite : ABAB ABAB - and c ;; [2] A |= C (C = 0x55) : xBxB xBxB - - cp d ;; [1] Test if pixel (A) is the old colour to be replaced (D) - jr nz, readPixelA ;; [2/3] If not equal go to next pixel + + ld l, a ;; [1] L = A current Byte of sprite : ABAB ABAB + and c ;; [2] A |= C (C = 0x55) : xBxB xBxB + + cp d ;; [1] Test if pixel (A) is the old colour to be replaced (D) + jr nz, readPixelA ;; [2/3] If not equal go to next pixel ld a, e ;; [1] else A = new colour to set (E) ;; Pixel Mode 0 = ABAB ABAB readPixelA: - ld h, a ;; [1] H = A (current colorized sprite) : xBxB xBxB - ld a, l ;; [1] L = A current Byte of sprite : ABAB ABAB - rrca ;; [1] A (current byte of sprite) >> 1 : ABAB ABAB -> xABA BABA - and c ;; [2] A |= Mask (0x55) : xAxA xAxA - - cp d ;; [1] Test if pixel (A) is the old colour to be replaced (D) - jr nz, readPixelB ;; [2/3] If not equal go to next pixel + ld h, a ;; [1] H = A (current colorized sprite) : xBxB xBxB + ld a, l ;; [1] L = A current Byte of sprite : ABAB ABAB + rrca ;; [1] A (current byte of sprite) >> 1 : ABAB ABAB -> xABA BABA + and c ;; [2] A |= Mask (0x55) : xAxA xAxA + + cp d ;; [1] Test if pixel (A) is the old colour to be replaced (D) + jr nz, readPixelB ;; [2/3] If not equal go to next pixel ld a, e ;; [1] else A = new colour to set (E) - + readPixelB: - rlca ;; [1] A = xAxA xAxA << 1 : AxAx AxAx - or h ;; [1] A |= H (xBxB xBxB) : ABAB ABAB + rlca ;; [1] A = xAxA xAxA << 1 : AxAx AxAx + or h ;; [1] A |= H (xBxB xBxB) : ABAB ABAB drawByte: exx ;; [1] Switch to Alternate registers - ld (sprite_color), a ;; [4] sprite_color = A (Sprite Byte) - - ld a, (de) ;; [2] Get next background byte into A - and (hl) ;; [2] Erase background part that is to be overwritten (Mask step 1) - inc hl ;; [3] HL += 1 => Point HL to Sprite Colour information + ld (sprite_color), a ;; [4] sprite_color = A (Sprite Byte) + + ld a, (de) ;; [2] Get next background byte into A + and (hl) ;; [2] Erase background part that is to be overwritten (Mask step 1) + inc hl ;; [3] HL += 1 => Point HL to Sprite Colour information sprite_color = .+1 ;; Placeholder for the Sprite Color computed - or #00 ;; [2] Add up background and sprite information in one byte (Mask step 2) - ld (de), a ;; [2] Save modified background + sprite data information into memory - - inc hl ;; [2] Next byte sprite source - inc de ;; [2] Next byte Dest Memory - djnz lineLoop ;; [3] Decrement B (Width) if B != 0 goto lineLoop - - dec c ;; [1] Decrement C (Height) - jr z, end ;; [2/3] If C == O goto end + or #00 ;; [2] Add up background and sprite information in one byte (Mask step 2) + ld (de), a ;; [2] Save modified background + sprite data information into memory + + inc hl ;; [2] Next byte sprite source + inc de ;; [2] Next byte Dest Memory + djnz lineLoop ;; [3] Decrement B (Width) if B != 0 goto lineLoop + + dec c ;; [1] Decrement C (Height) + jr z, end ;; [2/3] If C == O goto end startLine = .+1 ;; Placeholder for the Start line adress - ld de, #0000 ;; [3] DE = Start Line + ld de, #0000 ;; [3] DE = Start Line ld a, d ;; [1] Start of next pixel line normally is 0x0800 bytes away. add #0x08 ;; [2] so we add it to DE (just by adding 0x08 to D) ld d, a ;; [1] - and #0x38 ;; [2] We check if we have crossed memory boundary (every 8 pixel lines).. - + and #0x38 ;; [2] We check if we have crossed memory boundary (every 8 pixel lines).. + jr nz, convertLoop ;; [2/3] .. by checking the 4 bits that identify present memory line. ;; .... If 0, we have crossed boundaries @@ -209,8 +209,8 @@ dms_sprite_8bit_boundary_crossed: ld a, d ;; [1] -- which effectively is the same as moving it 1 bank backwards and then adc #0xC0 ;; [2] -- 50 bytes forwards (which is what we want to move it to the next pixel line) ld d, a ;; [1] -- Calculations are made with 8 bit maths as it is faster than other alternatives here - - jr convertLoop ;; [3] Jump to continue with next pixel line + + jr convertLoop ;; [3] Jump to continue with next pixel line end: - ;; Return is included in bindings \ No newline at end of file + ;; Return is included in bindings \ No newline at end of file diff --git a/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteMaskedColorizeM0_asmbindings.s b/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteMaskedColorizeM0_asmbindings.s index 4959e2abc..48bc1ef3c 100644 --- a/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteMaskedColorizeM0_asmbindings.s +++ b/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteMaskedColorizeM0_asmbindings.s @@ -1,7 +1,7 @@ ;;-----------------------------LICENSE NOTICE------------------------------------ ;; This file is part of CPCtelera: An Amstrad CPC Game Engine -;; Copyright (C) 2017 Arnaud Bouche (Arnaud6128) -;; Copyright (C) 2017 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) +;; Copyright (C) 2018 Arnaud Bouche (@Arnaud6128) +;; Copyright (C) 2018 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) ;; ;; This program is free software: you can redistribute it and/or modify ;; it under the terms of the GNU Lesser General Public License as published by diff --git a/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteMaskedColorizeM0_cbindings.s b/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteMaskedColorizeM0_cbindings.s index 212a5acc5..18f336eb5 100644 --- a/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteMaskedColorizeM0_cbindings.s +++ b/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteMaskedColorizeM0_cbindings.s @@ -1,7 +1,7 @@ ;;-----------------------------LICENSE NOTICE------------------------------------ ;; This file is part of CPCtelera: An Amstrad CPC Game Engine -;; Copyright (C) 2017 Arnaud Bouche (Arnaud6128) -;; Copyright (C) 2017 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) +;; Copyright (C) 2018 Arnaud Bouche (@Arnaud6128) +;; Copyright (C) 2018 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) ;; ;; This program is free software: you can redistribute it and/or modify ;; it under the terms of the GNU Lesser General Public License as published by diff --git a/cpctelera/src/sprites/colorReplace/M0/cpct_spriteColorizeM0.asm b/cpctelera/src/sprites/colorReplace/M0/cpct_spriteColorizeM0.asm index 52f433ba3..f319db09c 100644 --- a/cpctelera/src/sprites/colorReplace/M0/cpct_spriteColorizeM0.asm +++ b/cpctelera/src/sprites/colorReplace/M0/cpct_spriteColorizeM0.asm @@ -1,7 +1,7 @@ ;;-----------------------------LICENSE NOTICE------------------------------------ ;; This file is part of CPCtelera: An Amstrad CPC Game Engine -;; Copyright (C) 2017 Arnaud Bouche -;; Copyright (C) 2017 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) +;; Copyright (C) 2018 Arnaud Bouche (@Arnaud6128) +;; Copyright (C) 2018 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) ;; ;; This program is free software: you can redistribute it and/or modify ;; it under the terms of the GNU Lesser General Public License as published by @@ -90,77 +90,77 @@ ;; Macro to convert Pixel to xAxC xBxD format .macro convertPixel - ;; From cpct_px2byteM0 - ld bc, #dc_mode0_ct ;; [3] BC points to conversion table (dc_mode0_ct) - - ;; Compute BC += A - add c ;; [1] | C += A - ld c, a ;; [1] | - sub a ;; [1] A = 0 (preserving Carry Flag) - adc b ;; [1] | B += Carry - ld b, a ;; [1] | + ;; From cpct_px2byteM0 + ld bc, #dc_mode0_ct ;; [3] BC points to conversion table (dc_mode0_ct) + + ;; Compute BC += A + add c ;; [1] | C += A + ld c, a ;; [1] | + sub a ;; [1] A = 0 (preserving Carry Flag) + adc b ;; [1] | B += Carry + ld b, a ;; [1] | ;; A = *(BC + A) ld a, (bc) ;; [2] A = Value stored at the table pointed by BC .endm - ;; Convert newColor to pixel format (E) - ld a, h ;; [1] A = H new color index - convertPixel ;; [10] | Convert into A - ld e, a ;; [1] | E = A new color : xAxC xBxD + ;; Convert newColor to pixel format (E) + ld a, h ;; [1] A = H new color index + convertPixel ;; [10] | Convert into A + ld e, a ;; [1] | E = A new color : xAxC xBxD - ;; Convert oldColor to pixel format (D) - ld a, l ;; [1] A = L old color index - convertPixel ;; [10] | Convert into A - ld d, a ;; [1] | D = A old color : xAxC xBxD - - ld c, #0x55 ;; [2] C = Mask to get pixel A : xAxC xBxD - exx ;; [1] Switch to Alternate registers - - ld__ixl_c ;; [1] IXL = C (Width) - ld c, b ;; [1] C = B (Height) - -convertLoop: - ld__b_ixl ;; [2] B = IXL (Sprite Width) - + ;; Convert oldColor to pixel format (D) + ld a, l ;; [1] A = L old color index + convertPixel ;; [10] | Convert into A + ld d, a ;; [1] | D = A old color : xAxC xBxD + + ld c, #0x55 ;; [2] C = Mask to get pixel A : xAxC xBxD + exx ;; [1] Switch to Alternate registers + + ld__ixl_c ;; [1] IXL = C (Width) + ld c, b ;; [1] C = B (Height) + +convertLoop: + ld__b_ixl ;; [2] B = IXL (Sprite Width) + lineLoop: - ld a, (hl) ;; [2] A = (HL) current Byte of sprite + ld a, (hl) ;; [2] A = (HL) current Byte of sprite exx ;; [1] Switch to Default registers - - ld l, a ;; [1] L = A current Byte of sprite : ABAB ABAB - and c ;; [2] A |= C (C = 0x55) : xBxB xBxB - - cp d ;; [1] Test if pixel (A) is the old colour to be replaced (D) - jr nz, readPixelA ;; [2/3] If not equal go to next pixel + + ld l, a ;; [1] L = A current Byte of sprite : ABAB ABAB + and c ;; [2] A |= C (C = 0x55) : xBxB xBxB + + cp d ;; [1] Test if pixel (A) is the old colour to be replaced (D) + jr nz, readPixelA ;; [2/3] If not equal go to next pixel ld a, e ;; [1] else A = new colour to set (E) ;; Pixel Mode 0 = ABAB ABAB readPixelA: - ld h, a ;; [1] H = A (current colorized sprite) : xBxB xBxB - ld a, l ;; [1] L = A current Byte of sprite : ABAB ABAB - rrca ;; [1] A (current byte of sprite) >> 1 : ABAB ABAB -> xABA BABA - and c ;; [2] A |= Mask (0x55) : xAxA xAxA - - cp d ;; [1] Test if pixel (A) is the old colour to be replaced (D) - jr nz, readPixelB ;; [2/3] If not equal go to next pixel + ld h, a ;; [1] H = A (current colorized sprite) : xBxB xBxB + ld a, l ;; [1] L = A current Byte of sprite : ABAB ABAB + rrca ;; [1] A (current byte of sprite) >> 1 : ABAB ABAB -> xABA BABA + and c ;; [2] A |= Mask (0x55) : xAxA xAxA + + cp d ;; [1] Test if pixel (A) is the old colour to be replaced (D) + jr nz, readPixelB ;; [2/3] If not equal go to next pixel ld a, e ;; [1] else A = new colour to set (E) - + readPixelB: - rlca ;; [1] A = xAxA xAxA << 1 : AxAx AxAx - or h ;; [1] A |= H (xBxB xBxB) : ABAB ABAB + rlca ;; [1] A = xAxA xAxA << 1 : AxAx AxAx + or h ;; [1] A |= H (xBxB xBxB) : ABAB ABAB setByte: - exx ;; [1] Switch to Alternate registers + exx ;; [1] Switch to Alternate registers - ld (de), a ;; [2] Update current sprite byte with pixels - inc hl ;; [2] Next byte sprite source - inc de ;; [2] Next byte sprite colorized - djnz lineLoop ;; [3] Decrement B (Width) if != 0 goto lineLoop - -nextLine: - dec c ;; [1] Decrement C (Height) - jr nz, convertLoop ;; [2/3] If != O goto convertLoop - + ld (de), a ;; [2] Update current sprite byte with pixels + inc hl ;; [2] Next byte sprite source + inc de ;; [2] Next byte sprite colorized + djnz lineLoop ;; [3] Decrement B (Width) if != 0 goto lineLoop + +nextLine: + dec c ;; [1] Decrement C (Height) + jr nz, convertLoop ;; [2/3] If != O goto convertLoop + end: - ;; Return is included in bindings - + ;; Return is included in bindings + diff --git a/cpctelera/src/sprites/colorReplace/M0/cpct_spriteColorizeM0_asmbindings.s b/cpctelera/src/sprites/colorReplace/M0/cpct_spriteColorizeM0_asmbindings.s index 01f6d77b7..3339b8ea5 100644 --- a/cpctelera/src/sprites/colorReplace/M0/cpct_spriteColorizeM0_asmbindings.s +++ b/cpctelera/src/sprites/colorReplace/M0/cpct_spriteColorizeM0_asmbindings.s @@ -1,7 +1,7 @@ ;;-----------------------------LICENSE NOTICE------------------------------------ ;; This file is part of CPCtelera: An Amstrad CPC Game Engine -;; Copyright (C) 2017 Arnaud Bouche (Arnaud6128) -;; Copyright (C) 2017 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) +;; Copyright (C) 2018 Arnaud Bouche (@Arnaud6128) +;; Copyright (C) 2018 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) ;; ;; This program is free software: you can redistribute it and/or modify ;; it under the terms of the GNU Lesser General Public License as published by diff --git a/cpctelera/src/sprites/colorReplace/M0/cpct_spriteColorizeM0_cbindings.s b/cpctelera/src/sprites/colorReplace/M0/cpct_spriteColorizeM0_cbindings.s index 63dbf05a5..27d164918 100644 --- a/cpctelera/src/sprites/colorReplace/M0/cpct_spriteColorizeM0_cbindings.s +++ b/cpctelera/src/sprites/colorReplace/M0/cpct_spriteColorizeM0_cbindings.s @@ -1,7 +1,7 @@ ;;-----------------------------LICENSE NOTICE------------------------------------ ;; This file is part of CPCtelera: An Amstrad CPC Game Engine -;; Copyright (C) 2017 Arnaud Bouche -;; Copyright (C) 2017 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) +;; Copyright (C) 2018 Arnaud Bouche (@Arnaud6128) +;; Copyright (C) 2018 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) ;; ;; This program is free software: you can redistribute it and/or modify ;; it under the terms of the GNU Lesser General Public License as published by diff --git a/cpctelera/src/sprites/colorReplace/M0/cpct_spriteMaskedColorizeM0.asm b/cpctelera/src/sprites/colorReplace/M0/cpct_spriteMaskedColorizeM0.asm index d6662e5c2..37a32f02e 100644 --- a/cpctelera/src/sprites/colorReplace/M0/cpct_spriteMaskedColorizeM0.asm +++ b/cpctelera/src/sprites/colorReplace/M0/cpct_spriteMaskedColorizeM0.asm @@ -1,7 +1,7 @@ ;;-----------------------------LICENSE NOTICE------------------------------------ ;; This file is part of CPCtelera: An Amstrad CPC Game Engine -;; Copyright (C) 2017 Arnaud Bouche (Arnaud6128) -;; Copyright (C) 2017 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) +;; Copyright (C) 2018 Arnaud Bouche (@Arnaud6128) +;; Copyright (C) 2018 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) ;; ;; This program is free software: you can redistribute it and/or modify ;; it under the terms of the GNU Lesser General Public License as published by @@ -96,80 +96,80 @@ ;; Macro to convert Pixel to xAxC xBxD format .macro convertPixel - ;; From cpct_px2byteM0 - ld bc, #dc_mode0_ct ;; [3] BC points to conversion table (dc_mode0_ct) - - ;; Compute BC += A - add c ;; [1] | C += A - ld c, a ;; [1] | - sub a ;; [1] A = 0 (preserving Carry Flag) - adc b ;; [1] | B += Carry - ld b, a ;; [1] | + ;; From cpct_px2byteM0 + ld bc, #dc_mode0_ct ;; [3] BC points to conversion table (dc_mode0_ct) + + ;; Compute BC += A + add c ;; [1] | C += A + ld c, a ;; [1] | + sub a ;; [1] A = 0 (preserving Carry Flag) + adc b ;; [1] | B += Carry + ld b, a ;; [1] | ;; A = *(BC + A) ld a, (bc) ;; [2] A = Value stored at the table pointed by BC .endm - ;; Convert newColor to pixel format (E) - ld a, h ;; [1] A = H new color index - convertPixel ;; [10] | Convert into A - ld e, a ;; [1] | E = A new color : xAxC xBxD + ;; Convert newColor to pixel format (E) + ld a, h ;; [1] A = H new color index + convertPixel ;; [10] | Convert into A + ld e, a ;; [1] | E = A new color : xAxC xBxD - ;; Convert oldColor to pixel format (D) - ld a, l ;; [1] A = L old color index - convertPixel ;; [10] | Convert into A - ld d, a ;; [1] | D = A old color : xAxC xBxD - - ld c, #0x55 ;; [2] C = Mask to get pixel A : xAxC xBxD - exx ;; [1] Switch to Alternate registers - - ld__ixl_c ;; [1] IXL = C (Width) - ld c, b ;; [1] C = B (Height) - -convertLoop: - ld__b_ixl ;; [2] B = IXL (Sprite Width) + ;; Convert oldColor to pixel format (D) + ld a, l ;; [1] A = L old color index + convertPixel ;; [10] | Convert into A + ld d, a ;; [1] | D = A old color : xAxC xBxD + + ld c, #0x55 ;; [2] C = Mask to get pixel A : xAxC xBxD + exx ;; [1] Switch to Alternate registers + + ld__ixl_c ;; [1] IXL = C (Width) + ld c, b ;; [1] C = B (Height) + +convertLoop: + ld__b_ixl ;; [2] B = IXL (Sprite Width) lineLoop: - ld a, (hl) ;; [2] A = (HL) current Byte of sprite Mask - ld (de), a ;; [2] (DE) = A Copy of sprite Mask - inc hl ;; [2] Next byte sprite Color source - inc de ;; [2] Next byte sprite Color destination - ld a, (hl) ;; [2] A = (HL) current Byte of sprite Color - + ld a, (hl) ;; [2] A = (HL) current Byte of sprite Mask + ld (de), a ;; [2] (DE) = A Copy of sprite Mask + inc hl ;; [2] Next byte sprite Color source + inc de ;; [2] Next byte sprite Color destination + ld a, (hl) ;; [2] A = (HL) current Byte of sprite Color + exx ;; [1] Switch to Default registers - - ld l, a ;; [1] L = A current Byte of sprite : ABAB ABAB - and c ;; [2] A |= C (C = 0x55) : xBxB xBxB - - cp d ;; [1] Test if pixel (A) is the old colour to be replaced (D) - jr nz, readPixelA ;; [2/3] If not equal go to next pixel + + ld l, a ;; [1] L = A current Byte of sprite : ABAB ABAB + and c ;; [2] A |= C (C = 0x55) : xBxB xBxB + + cp d ;; [1] Test if pixel (A) is the old colour to be replaced (D) + jr nz, readPixelA ;; [2/3] If not equal go to next pixel ld a, e ;; [1] else A = new colour to set (E) ;; Pixel Mode 0 = ABAB ABAB readPixelA: - ld h, a ;; [1] H = A (current colorized sprite) : xBxB xBxB - ld a, l ;; [1] L = A current Byte of sprite : ABAB ABAB - rrca ;; [1] A (current byte of sprite) >> 1 : ABAB ABAB -> xABA BABA - and c ;; [2] A |= Mask (0x55) : xAxA xAxA - - cp d ;; [1] Test if pixel (A) is the old colour to be replaced (D) - jr nz, readPixelB ;; [2/3] If not equal go to next pixel + ld h, a ;; [1] H = A (current colorized sprite) : xBxB xBxB + ld a, l ;; [1] L = A current Byte of sprite : ABAB ABAB + rrca ;; [1] A (current byte of sprite) >> 1 : ABAB ABAB -> xABA BABA + and c ;; [2] A |= Mask (0x55) : xAxA xAxA + + cp d ;; [1] Test if pixel (A) is the old colour to be replaced (D) + jr nz, readPixelB ;; [2/3] If not equal go to next pixel ld a, e ;; [1] else A = new colour to set (E) - + readPixelB: - rlca ;; [1] A = xAxA xAxA << 1 : AxAx AxAx - or h ;; [1] A |= H (xBxB xBxB) : ABAB ABAB + rlca ;; [1] A = xAxA xAxA << 1 : AxAx AxAx + or h ;; [1] A |= H (xBxB xBxB) : ABAB ABAB setByte: - exx ;; [1] Switch to Alternate registers - - ld (de), a ;; [2] Update current sprite byte with pixels - inc hl ;; [2] Next byte sprite source - inc de ;; [2] Next byte sprite colorized - djnz lineLoop ;; [3] Decrement B (Width) if != 0 goto lineLoop - - dec c ;; [1] Decrement C (Height) - jr nz, convertLoop ;; [2/3] If C == O goto end + exx ;; [1] Switch to Alternate registers + + ld (de), a ;; [2] Update current sprite byte with pixels + inc hl ;; [2] Next byte sprite source + inc de ;; [2] Next byte sprite colorized + djnz lineLoop ;; [3] Decrement B (Width) if != 0 goto lineLoop + + dec c ;; [1] Decrement C (Height) + jr nz, convertLoop ;; [2/3] If C == O goto end end: - ;; Return is included in bindings \ No newline at end of file + ;; Return is included in bindings \ No newline at end of file diff --git a/cpctelera/src/sprites/colorReplace/M0/cpct_spriteMaskedColorizeM0_asmbindings.s b/cpctelera/src/sprites/colorReplace/M0/cpct_spriteMaskedColorizeM0_asmbindings.s index 9abbc1467..04b8fcf88 100644 --- a/cpctelera/src/sprites/colorReplace/M0/cpct_spriteMaskedColorizeM0_asmbindings.s +++ b/cpctelera/src/sprites/colorReplace/M0/cpct_spriteMaskedColorizeM0_asmbindings.s @@ -1,7 +1,7 @@ ;;-----------------------------LICENSE NOTICE------------------------------------ ;; This file is part of CPCtelera: An Amstrad CPC Game Engine -;; Copyright (C) 2017 Arnaud Bouche (Arnaud6128) -;; Copyright (C) 2017 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) +;; Copyright (C) 2018 Arnaud Bouche (@Arnaud6128) +;; Copyright (C) 2018 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) ;; ;; This program is free software: you can redistribute it and/or modify ;; it under the terms of the GNU Lesser General Public License as published by diff --git a/cpctelera/src/sprites/colorReplace/M0/cpct_spriteMaskedColorizeM0_cbindings.s b/cpctelera/src/sprites/colorReplace/M0/cpct_spriteMaskedColorizeM0_cbindings.s index 9c9363f91..3dad1ae84 100644 --- a/cpctelera/src/sprites/colorReplace/M0/cpct_spriteMaskedColorizeM0_cbindings.s +++ b/cpctelera/src/sprites/colorReplace/M0/cpct_spriteMaskedColorizeM0_cbindings.s @@ -1,7 +1,7 @@ ;;-----------------------------LICENSE NOTICE------------------------------------ ;; This file is part of CPCtelera: An Amstrad CPC Game Engine -;; Copyright (C) 2017 Arnaud Bouche (Arnaud6128) -;; Copyright (C) 2017 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) +;; Copyright (C) 2018 Arnaud Bouche (@Arnaud6128) +;; Copyright (C) 2018 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) ;; ;; This program is free software: you can redistribute it and/or modify ;; it under the terms of the GNU Lesser General Public License as published by diff --git a/cpctelera/src/sprites/colorReplace/M1/cpct_drawSpriteColorizeM1.asm b/cpctelera/src/sprites/colorReplace/M1/cpct_drawSpriteColorizeM1.asm index c6b6b8614..639f3ced5 100644 --- a/cpctelera/src/sprites/colorReplace/M1/cpct_drawSpriteColorizeM1.asm +++ b/cpctelera/src/sprites/colorReplace/M1/cpct_drawSpriteColorizeM1.asm @@ -1,7 +1,7 @@ ;;-----------------------------LICENSE NOTICE------------------------------------ ;; This file is part of CPCtelera: An Amstrad CPC Game Engine -;; Copyright (C) 2017 Arnaud Bouche (Arnaud6128) -;; Copyright (C) 2017 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) +;; Copyright (C) 2018 Arnaud Bouche (@Arnaud6128) +;; Copyright (C) 2018 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) ;; ;; This program is free software: you can redistribute it and/or modify ;; it under the terms of the GNU Lesser General Public License as published by @@ -103,113 +103,113 @@ .globl dc_mode1_ct ;; Macro to convert color to pixel Mode1 : Axxx Axxx -.macro convertPixel ;; From cpct_px2byteM1 - ld bc, #dc_mode1_ct ;; [3] BC points to conversion table (dc_mode1_ct) - - ;; Compute BC += A - add c ;; [1] | C += A - ld c, a ;; [1] | - sub a ;; [1] A = 0 (preserving Carry Flag) - adc b ;; [1] | B += Carry - ld b, a ;; [1] | +.macro convertPixel ;; From cpct_px2byteM1 + ld bc, #dc_mode1_ct ;; [3] BC points to conversion table (dc_mode1_ct) + + ;; Compute BC += A + add c ;; [1] | C += A + ld c, a ;; [1] | + sub a ;; [1] A = 0 (preserving Carry Flag) + adc b ;; [1] | B += Carry + ld b, a ;; [1] | ;; A = *(BC + A) ld a, (bc) ;; [2] A = Value stored at the table pointed by BC .endm - ;; Convert newColor to pixel format (E) - ld a, h ;; [1] A = H new color index - convertPixel ;; [10] | Convert into A - ld e, a ;; [1] | E = A new color : Axxx Axxx + ;; Convert newColor to pixel format (E) + ld a, h ;; [1] A = H new color index + convertPixel ;; [10] | Convert into A + ld e, a ;; [1] | E = A new color : Axxx Axxx - ;; Convert oldColor to pixel format (D) - ld a, l ;; [1] A = L old color index - convertPixel ;; [10] | Convert into A - ld d, a ;; [1] | D = A old color : Axxx Axxx - - ld c, #0x88 ;; [2] C = Mask to get pixel A : Axxx Axxx - exx ;; [1] Switch to Alternate registers - - ld__ixl_c ;; [1] IXL = C (Width) - ld c, b ;; [1] C = B (Height) - -convertLoop: - ld (startLine), de ;; [6] Store DE start line (DestMem) - ld__b_ixl ;; [2] B = IXL (Sprite Width) - + ;; Convert oldColor to pixel format (D) + ld a, l ;; [1] A = L old color index + convertPixel ;; [10] | Convert into A + ld d, a ;; [1] | D = A old color : Axxx Axxx + + ld c, #0x88 ;; [2] C = Mask to get pixel A : Axxx Axxx + exx ;; [1] Switch to Alternate registers + + ld__ixl_c ;; [1] IXL = C (Width) + ld c, b ;; [1] C = B (Height) + +convertLoop: + ld (startLine), de ;; [6] Store DE start line (DestMem) + ld__b_ixl ;; [2] B = IXL (Sprite Width) + lineLoop: - ld a, (hl) ;; [2] A = (HL) current Byte of sprite + ld a, (hl) ;; [2] A = (HL) current Byte of sprite exx ;; [1] Switch to Default registers - - ld l, a ;; [1] L = A current Byte of sprite : ABCD ABCD - and c ;; [2] A |= C (C = 0x88) : Axxx Axxx - - cp d ;; [1] Test if pixel (A) is the old colour to be replaced (D) - jr nz, readPixelA ;; [2/3] If not equal go to next pixel + + ld l, a ;; [1] L = A current Byte of sprite : ABCD ABCD + and c ;; [2] A |= C (C = 0x88) : Axxx Axxx + + cp d ;; [1] Test if pixel (A) is the old colour to be replaced (D) + jr nz, readPixelA ;; [2/3] If not equal go to next pixel ld a, e ;; [1] else A = new colour to set (E) - + readPixelA: - ld h, a ;; [1] H = A (current colorized sprite) : Axxx Axxx - - sla l ;; [2] L (current byte of sprite) << 1 : ABCD ABCD -> BCDx BCDx - ld a, l ;; [1] A = L : BCDx BCDx - and c ;; [2] A |= Mask (0x88) : Bxxx Bxxx - - cp d ;; [1] Test if pixel (A) is the old colour to be replaced (D) - jr nz, readPixelB ;; [2/3] If not equal go to next pixel + ld h, a ;; [1] H = A (current colorized sprite) : Axxx Axxx + + sla l ;; [2] L (current byte of sprite) << 1 : ABCD ABCD -> BCDx BCDx + ld a, l ;; [1] A = L : BCDx BCDx + and c ;; [2] A |= Mask (0x88) : Bxxx Bxxx + + cp d ;; [1] Test if pixel (A) is the old colour to be replaced (D) + jr nz, readPixelB ;; [2/3] If not equal go to next pixel ld a, e ;; [1] else A = new colour to set (E) - + readPixelB: rrca ;; [1] A = Axxx Axxx >> 1 : xBxx xBxx - or h ;; [1] A |= H (color byte) : Axxx Axxx - ld h, a ;; [1] H = A : ABxx ABxx - - sla l ;; [2] L ( BCDx BCDx) << 1 : CDxx CDxx - ld a, l ;; [1] A = L : CDxx CDxx - and c ;; [1] A |= C (C = 0x88) : Cxxx Cxxx - - cp d ;; [1] Test if pixel (A) is the old colour to be replaced (D) - jr nz, readPixelC ;; [2/3] If not equal go to next pixel + or h ;; [1] A |= H (color byte) : Axxx Axxx + ld h, a ;; [1] H = A : ABxx ABxx + + sla l ;; [2] L ( BCDx BCDx) << 1 : CDxx CDxx + ld a, l ;; [1] A = L : CDxx CDxx + and c ;; [1] A |= C (C = 0x88) : Cxxx Cxxx + + cp d ;; [1] Test if pixel (A) is the old colour to be replaced (D) + jr nz, readPixelC ;; [2/3] If not equal go to next pixel ld a, e ;; [1] else A = new colour to set (E) - + readPixelC: - rrca ;; [1] A = Axxx Axxx >> 1 : xBxx xBxx - rrca ;; [1] A = xxCx xxCx << 1 : xxCx xxCx - or h ;; [1] A |= H (ABxx ABxx) : ABCx ABCx - ld h, a ;; [1] H = A : ABCx ABCx + rrca ;; [1] A = Axxx Axxx >> 1 : xBxx xBxx + rrca ;; [1] A = xxCx xxCx << 1 : xxCx xxCx + or h ;; [1] A |= H (ABxx ABxx) : ABCx ABCx + ld h, a ;; [1] H = A : ABCx ABCx - sla l ;; [2] L (BCDx BCDx) << 1 : Dxxx Dxxx - ld a, l ;; [1] A = L : Dxxx Dxxx - and c ;; [1] A |= C (C = 0x88) : Dxxx Dxxx - - cp d ;; [1] Test if pixel (A) is the old colour to be replaced (D) - jr nz, readPixelD ;; [2/3] If not equal go to next pixel + sla l ;; [2] L (BCDx BCDx) << 1 : Dxxx Dxxx + ld a, l ;; [1] A = L : Dxxx Dxxx + and c ;; [1] A |= C (C = 0x88) : Dxxx Dxxx + + cp d ;; [1] Test if pixel (A) is the old colour to be replaced (D) + jr nz, readPixelD ;; [2/3] If not equal go to next pixel ld a, e ;; [1] else A = new colour to set (E) - + readPixelD: - rrca ;; [1] A = Axxx Axxx >> 1 : xBxx xBxx - rrca ;; [1] A = xBxx xBxx >> 1 : xxCx xxCx - rrca ;; [1] A = xxCx xxxx >> 1 : xxxD xxxD - or h ;; [1] A |= H (ABCx ABCx) : ABCD ABCD + rrca ;; [1] A = Axxx Axxx >> 1 : xBxx xBxx + rrca ;; [1] A = xBxx xBxx >> 1 : xxCx xxCx + rrca ;; [1] A = xxCx xxxx >> 1 : xxxD xxxD + or h ;; [1] A |= H (ABCx ABCx) : ABCD ABCD - exx ;; [1] Switch to Alternate registers + exx ;; [1] Switch to Alternate registers - ld (de), a ;; [2] Update current sprite byte with pixels - inc hl ;; [2] Next byte sprite source - inc de ;; [2] Next byte sprite colorized - djnz lineLoop ;; [3] Decrement B (Width) if B != 0 goto lineLoop - - dec c ;; [1] Decrement C (Height) - jr z, end ;; [2/3] If C == O goto end + ld (de), a ;; [2] Update current sprite byte with pixels + inc hl ;; [2] Next byte sprite source + inc de ;; [2] Next byte sprite colorized + djnz lineLoop ;; [3] Decrement B (Width) if B != 0 goto lineLoop + + dec c ;; [1] Decrement C (Height) + jr z, end ;; [2/3] If C == O goto end startLine = .+1 ;; Placeholder for the Start line adress - ld de, #0000 ;; [3] DE = Start Line + ld de, #0000 ;; [3] DE = Start Line ld a, d ;; [1] Start of next pixel line normally is 0x0800 bytes away. add #0x08 ;; [2] so we add it to DE (just by adding 0x08 to D) ld d, a ;; [1] - and #0x38 ;; [2] We check if we have crossed memory boundary (every 8 pixel lines).. - + and #0x38 ;; [2] We check if we have crossed memory boundary (every 8 pixel lines).. + jr nz, convertLoop ;; [2/3] .. by checking the 4 bits that identify present memory line. ;; .... If 0, we have crossed boundaries @@ -220,9 +220,9 @@ dms_sprite_8bit_boundary_crossed: ld a, d ;; [1] -- which effectively is the same as moving it 1 bank backwards and then adc #0xC0 ;; [2] -- 50 bytes forwards (which is what we want to move it to the next pixel line) ld d, a ;; [1] -- Calculations are made with 8 bit maths as it is faster than other alternatives here - - jr convertLoop ;; [3] Jump to continue with next pixel line + + jr convertLoop ;; [3] Jump to continue with next pixel line end: - ;; Return is included in bindings - + ;; Return is included in bindings + diff --git a/cpctelera/src/sprites/colorReplace/M1/cpct_drawSpriteColorizeM1_asmbindings.s b/cpctelera/src/sprites/colorReplace/M1/cpct_drawSpriteColorizeM1_asmbindings.s index e0ed27aff..334f8da86 100644 --- a/cpctelera/src/sprites/colorReplace/M1/cpct_drawSpriteColorizeM1_asmbindings.s +++ b/cpctelera/src/sprites/colorReplace/M1/cpct_drawSpriteColorizeM1_asmbindings.s @@ -1,7 +1,7 @@ ;;-----------------------------LICENSE NOTICE------------------------------------ ;; This file is part of CPCtelera: An Amstrad CPC Game Engine -;; Copyright (C) 2017 Arnaud Bouche (Arnaud6128) -;; Copyright (C) 2017 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) +;; Copyright (C) 2018 Arnaud Bouche (@Arnaud6128) +;; Copyright (C) 2018 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) ;; ;; This program is free software: you can redistribute it and/or modify ;; it under the terms of the GNU Lesser General Public License as published by diff --git a/cpctelera/src/sprites/colorReplace/M1/cpct_drawSpriteColorizeM1_cbindings.s b/cpctelera/src/sprites/colorReplace/M1/cpct_drawSpriteColorizeM1_cbindings.s index 21322d77c..32ef19867 100644 --- a/cpctelera/src/sprites/colorReplace/M1/cpct_drawSpriteColorizeM1_cbindings.s +++ b/cpctelera/src/sprites/colorReplace/M1/cpct_drawSpriteColorizeM1_cbindings.s @@ -1,7 +1,7 @@ ;;-----------------------------LICENSE NOTICE------------------------------------ ;; This file is part of CPCtelera: An Amstrad CPC Game Engine -;; Copyright (C) 2017 Arnaud Bouche (Arnaud6128) -;; Copyright (C) 2017 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) +;; Copyright (C) 2018 Arnaud Bouche (@Arnaud6128) +;; Copyright (C) 2018 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) ;; ;; This program is free software: you can redistribute it and/or modify ;; it under the terms of the GNU Lesser General Public License as published by diff --git a/cpctelera/src/sprites/colorReplace/M1/cpct_drawSpriteMaskedAlignedColorizeM1.asm b/cpctelera/src/sprites/colorReplace/M1/cpct_drawSpriteMaskedAlignedColorizeM1.asm index cbb50cdb3..3abd98527 100644 --- a/cpctelera/src/sprites/colorReplace/M1/cpct_drawSpriteMaskedAlignedColorizeM1.asm +++ b/cpctelera/src/sprites/colorReplace/M1/cpct_drawSpriteMaskedAlignedColorizeM1.asm @@ -1,7 +1,7 @@ ;;-----------------------------LICENSE NOTICE------------------------------------ ;; This file is part of CPCtelera: An Amstrad CPC Game Engine -;; Copyright (C) 2017 Arnaud Bouche (Arnaud6128) -;; Copyright (C) 2017 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) +;; Copyright (C) 2018 Arnaud Bouche (@Arnaud6128) +;; Copyright (C) 2018 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) ;; ;; This program is free software: you can redistribute it and/or modify ;; it under the terms of the GNU Lesser General Public License as published by @@ -105,121 +105,121 @@ .globl dc_mode1_ct ;; Macro to convert color to pixel Mode1 : Axxx Axxx -.macro convertPixel ;; From cpct_px2byteM1 - ld bc, #dc_mode1_ct ;; [3] BC points to conversion table (dc_mode1_ct) - - ;; Compute BC += A - add c ;; [1] | C += A - ld c, a ;; [1] | - sub a ;; [1] A = 0 (preserving Carry Flag) - adc b ;; [1] | B += Carry - ld b, a ;; [1] | +.macro convertPixel ;; From cpct_px2byteM1 + ld bc, #dc_mode1_ct ;; [3] BC points to conversion table (dc_mode1_ct) + + ;; Compute BC += A + add c ;; [1] | C += A + ld c, a ;; [1] | + sub a ;; [1] A = 0 (preserving Carry Flag) + adc b ;; [1] | B += Carry + ld b, a ;; [1] | ;; A = *(BC + A) ld a, (bc) ;; [2] A = Value stored at the table pointed by HL .endm - ;; Convert newColor to pixel format (E) - ld a, h ;; [1] A = H new color index - convertPixel ;; [10] | Convert into A - ld e, a ;; [1] | E = A new color : Axxx Axxx + ;; Convert newColor to pixel format (E) + ld a, h ;; [1] A = H new color index + convertPixel ;; [10] | Convert into A + ld e, a ;; [1] | E = A new color : Axxx Axxx - ;; Convert oldColor to pixel format (D) - ld a, l ;; [1] A = L old color index - convertPixel ;; [10] | Convert into A - ld d, a ;; [1] | D = A old color : Axxx Axxx - - ld c, #0x88 ;; [2] C = Mask to get pixel A : Axxx Axxx - exx ;; [1] Switch to Alternate registers - - ld__ixl_c ;; [1] IXL = C (Width) - ld c, b ;; [1] C = B (Height) - -convertLoop: - push de ;; [4] Store DE start line (DestMem) - ld__b_ixl ;; [2] B = IXL (Sprite Width) - + ;; Convert oldColor to pixel format (D) + ld a, l ;; [1] A = L old color index + convertPixel ;; [10] | Convert into A + ld d, a ;; [1] | D = A old color : Axxx Axxx + + ld c, #0x88 ;; [2] C = Mask to get pixel A : Axxx Axxx + exx ;; [1] Switch to Alternate registers + + ld__ixl_c ;; [1] IXL = C (Width) + ld c, b ;; [1] C = B (Height) + +convertLoop: + push de ;; [4] Store DE start line (DestMem) + ld__b_ixl ;; [2] B = IXL (Sprite Width) + lineLoop: - ld a, (hl) ;; [2] A = (HL) current Byte of sprite Mask + ld a, (hl) ;; [2] A = (HL) current Byte of sprite Mask exx ;; [1] Switch to Default registers - - ld l, a ;; [1] L = A current Byte of sprite : ABCD ABCD - and c ;; [2] A |= C (C = 0x88) : Axxx Axxx - - cp d ;; [1] Test if pixel (A) is the old colour to be replaced (D) - jr nz, readPixelA ;; [2/3] If not equal go to next pixel + + ld l, a ;; [1] L = A current Byte of sprite : ABCD ABCD + and c ;; [2] A |= C (C = 0x88) : Axxx Axxx + + cp d ;; [1] Test if pixel (A) is the old colour to be replaced (D) + jr nz, readPixelA ;; [2/3] If not equal go to next pixel ld a, e ;; [1] else A = new colour to set (E) - + readPixelA: - ld h, a ;; [1] H = A (current colorized sprite) : Axxx Axxx - - sla l ;; [2] L (current byte of sprite) << 1 : ABCD ABCD -> BCDx BCDx - ld a, l ;; [1] A = L : BCDx BCDx - and c ;; [2] A |= Mask (0x88) : Bxxx Bxxx - - cp d ;; [1] Test if pixel (A) is the old colour to be replaced (D) - jr nz, readPixelB ;; [2/3] If not equal go to next pixel + ld h, a ;; [1] H = A (current colorized sprite) : Axxx Axxx + + sla l ;; [2] L (current byte of sprite) << 1 : ABCD ABCD -> BCDx BCDx + ld a, l ;; [1] A = L : BCDx BCDx + and c ;; [2] A |= Mask (0x88) : Bxxx Bxxx + + cp d ;; [1] Test if pixel (A) is the old colour to be replaced (D) + jr nz, readPixelB ;; [2/3] If not equal go to next pixel ld a, e ;; [1] else A = new colour to set (E) - + readPixelB: rrca ;; [1] A = Axxx Axxx >> 1 : xBxx xBxx - or h ;; [1] A |= H (color byte) : Axxx Axxx - ld h, a ;; [1] H = A : ABxx ABxx - - sla l ;; [2] L ( BCDx BCDx) << 1 : CDxx CDxx - ld a, l ;; [1] A = L : CDxx CDxx - and c ;; [1] A |= C (C = 0x88) : Cxxx Cxxx - - cp d ;; [1] Test if pixel (A) is the old colour to be replaced (D) - jr nz, readPixelC ;; [2/3] If not equal go to next pixel + or h ;; [1] A |= H (color byte) : Axxx Axxx + ld h, a ;; [1] H = A : ABxx ABxx + + sla l ;; [2] L ( BCDx BCDx) << 1 : CDxx CDxx + ld a, l ;; [1] A = L : CDxx CDxx + and c ;; [1] A |= C (C = 0x88) : Cxxx Cxxx + + cp d ;; [1] Test if pixel (A) is the old colour to be replaced (D) + jr nz, readPixelC ;; [2/3] If not equal go to next pixel ld a, e ;; [1] else A = new colour to set (E) - + readPixelC: - rrca ;; [1] A = Axxx Axxx >> 1 : xBxx xBxx - rrca ;; [1] A = xxCx xxCx << 1 : xxCx xxCx - or h ;; [1] A |= H (ABxx ABxx) : ABCx ABCx - ld h, a ;; [1] H = A : ABCx ABCx + rrca ;; [1] A = Axxx Axxx >> 1 : xBxx xBxx + rrca ;; [1] A = xxCx xxCx << 1 : xxCx xxCx + or h ;; [1] A |= H (ABxx ABxx) : ABCx ABCx + ld h, a ;; [1] H = A : ABCx ABCx - sla l ;; [2] L (BCDx BCDx) << 1 : Dxxx Dxxx - ld a, l ;; [1] A = L : Dxxx Dxxx - and c ;; [1] A |= C (C = 0x88) : Dxxx Dxxx - - cp d ;; [1] Test if pixel (A) is the old colour to be replaced (D) - jr nz, readPixelD ;; [2/3] If not equal go to next pixel + sla l ;; [2] L (BCDx BCDx) << 1 : Dxxx Dxxx + ld a, l ;; [1] A = L : Dxxx Dxxx + and c ;; [1] A |= C (C = 0x88) : Dxxx Dxxx + + cp d ;; [1] Test if pixel (A) is the old colour to be replaced (D) + jr nz, readPixelD ;; [2/3] If not equal go to next pixel ld a, e ;; [1] else A = new colour to set (E) - + readPixelD: - rrca ;; [1] A = Axxx Axxx >> 1 : xBxx xBxx - rrca ;; [1] A = xBxx xBxx >> 1 : xxCx xxCx - rrca ;; [1] A = xxCx xxxx >> 1 : xxxD xxxD - or h ;; [1] A |= H (ABCx ABCx) : ABCD ABCD + rrca ;; [1] A = Axxx Axxx >> 1 : xBxx xBxx + rrca ;; [1] A = xBxx xBxx >> 1 : xxCx xxCx + rrca ;; [1] A = xxCx xxxx >> 1 : xxxD xxxD + or h ;; [1] A |= H (ABCx ABCx) : ABCD ABCD - exx ;; [1] Switch to Alternate registers + exx ;; [1] Switch to Alternate registers drawByte: push hl ;; [4] Store HL (current byte sprite source) ld h, b ;; [1] H = B (Masked table adress High Byte) - ld l, a ;; [1] Access mask table element (table must be 256-byte aligned) - ld a, (de) ;; [2] Get the value of the byte of the screen where we are going to draw - and (hl) ;; [2] Erase background part that is to be overwritten (Mask step 1) - or l ;; [1] Add up background and sprite information in one byte (Mask step 2) - ld (de), a ;; [2] Save modified background + sprite data information into memory - pop hl ;; [3] Recover HL (current byte sprite source) - - inc hl ;; [2] Next byte sprite source - inc de ;; [2] Next byte sprite colorized - djnz lineLoop ;; [3] Decrement B (Width) if B != 0 goto lineLoop - - dec c ;; [1] Decrement C (Height) - jr z, end ;; [2/3] If C == O goto end + ld l, a ;; [1] Access mask table element (table must be 256-byte aligned) + ld a, (de) ;; [2] Get the value of the byte of the screen where we are going to draw + and (hl) ;; [2] Erase background part that is to be overwritten (Mask step 1) + or l ;; [1] Add up background and sprite information in one byte (Mask step 2) + ld (de), a ;; [2] Save modified background + sprite data information into memory + pop hl ;; [3] Recover HL (current byte sprite source) + + inc hl ;; [2] Next byte sprite source + inc de ;; [2] Next byte sprite colorized + djnz lineLoop ;; [3] Decrement B (Width) if B != 0 goto lineLoop + + dec c ;; [1] Decrement C (Height) + jr z, end ;; [2/3] If C == O goto end - pop de ;; [3] Restore DE start line (DestMem + pop de ;; [3] Restore DE start line (DestMem ld a, d ;; [1] Start of next pixel line normally is 0x0800 bytes away. add #0x08 ;; [2] so we add it to DE (just by adding 0x08 to D) ld d, a ;; [1] - and #0x38 ;; [2] We check if we have crossed memory boundary (every 8 pixel lines).. - + and #0x38 ;; [2] We check if we have crossed memory boundary (every 8 pixel lines).. + jr nz, convertLoop ;; [2/3] .. by checking the 4 bits that identify present memory line. ;; .... If 0, we have crossed boundaries @@ -230,10 +230,10 @@ dms_sprite_8bit_boundary_crossed: ld a, d ;; [1] -- which effectively is the same as moving it 1 bank backwards and then adc #0xC0 ;; [2] -- 50 bytes forwards (which is what we want to move it to the next pixel line) ld d, a ;; [1] -- Calculations are made with 8 bit maths as it is faster than other alternatives here - - jr convertLoop ;; [3] Jump to continue with next pixel line + + jr convertLoop ;; [3] Jump to continue with next pixel line end: pop de ;; [3] Empty stack by getting last element (DestMem) - ;; Return is included in bindings - + ;; Return is included in bindings + diff --git a/cpctelera/src/sprites/colorReplace/M1/cpct_drawSpriteMaskedAlignedColorizeM1_asmbindings.s b/cpctelera/src/sprites/colorReplace/M1/cpct_drawSpriteMaskedAlignedColorizeM1_asmbindings.s index 853ba0bbe..26f317d9b 100644 --- a/cpctelera/src/sprites/colorReplace/M1/cpct_drawSpriteMaskedAlignedColorizeM1_asmbindings.s +++ b/cpctelera/src/sprites/colorReplace/M1/cpct_drawSpriteMaskedAlignedColorizeM1_asmbindings.s @@ -1,7 +1,7 @@ ;;-----------------------------LICENSE NOTICE------------------------------------ ;; This file is part of CPCtelera: An Amstrad CPC Game Engine -;; Copyright (C) 2017 Arnaud Bouche (Arnaud6128) -;; Copyright (C) 2017 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) +;; Copyright (C) 2018 Arnaud Bouche (@Arnaud6128) +;; Copyright (C) 2018 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) ;; ;; This program is free software: you can redistribute it and/or modify ;; it under the terms of the GNU Lesser General Public License as published by diff --git a/cpctelera/src/sprites/colorReplace/M1/cpct_drawSpriteMaskedAlignedColorizeM1_cbindings.s b/cpctelera/src/sprites/colorReplace/M1/cpct_drawSpriteMaskedAlignedColorizeM1_cbindings.s index 9085b4a80..f88de196c 100644 --- a/cpctelera/src/sprites/colorReplace/M1/cpct_drawSpriteMaskedAlignedColorizeM1_cbindings.s +++ b/cpctelera/src/sprites/colorReplace/M1/cpct_drawSpriteMaskedAlignedColorizeM1_cbindings.s @@ -42,10 +42,10 @@ _cpct_drawSpriteMaskedAlignedColorizeM1:: ex (sp), hl ;; [6] HL = Table Mask address ;; ... and leave Return Address at (SP) as we don't need to restore ;; ... stack status because callin convention is __z88dk_callee - + ex de, hl ;; [1] HL <-> DE - - + + .include /cpct_drawSpriteMaskedAlignedColorizeM1.asm/ dms_restore_ix: diff --git a/cpctelera/src/sprites/colorReplace/M1/cpct_drawSpriteMaskedColorizeM1.asm b/cpctelera/src/sprites/colorReplace/M1/cpct_drawSpriteMaskedColorizeM1.asm index 9188f2ef3..c49b89f33 100644 --- a/cpctelera/src/sprites/colorReplace/M1/cpct_drawSpriteMaskedColorizeM1.asm +++ b/cpctelera/src/sprites/colorReplace/M1/cpct_drawSpriteMaskedColorizeM1.asm @@ -1,7 +1,7 @@ ;;-----------------------------LICENSE NOTICE------------------------------------ ;; This file is part of CPCtelera: An Amstrad CPC Game Engine -;; Copyright (C) 2017 Arnaud Bouche (Arnaud6128) -;; Copyright (C) 2017 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) +;; Copyright (C) 2018 Arnaud Bouche (@Arnaud6128) +;; Copyright (C) 2018 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) ;; ;; This program is free software: you can redistribute it and/or modify ;; it under the terms of the GNU Lesser General Public License as published by @@ -108,126 +108,126 @@ .globl dc_mode1_ct ;; Macro to convert color to pixel Mode1 : Axxx Axxx -.macro convertPixel ;; From cpct_px2byteM1 - ld bc, #dc_mode1_ct ;; [3] BC points to conversion table (dc_mode1_ct) - - ;; Compute BC += A - add c ;; [1] | C += A - ld c, a ;; [1] | - sub a ;; [1] A = 0 (preserving Carry Flag) - adc b ;; [1] | B += Carry - ld b, a ;; [1] | +.macro convertPixel ;; From cpct_px2byteM1 + ld bc, #dc_mode1_ct ;; [3] BC points to conversion table (dc_mode1_ct) + + ;; Compute BC += A + add c ;; [1] | C += A + ld c, a ;; [1] | + sub a ;; [1] A = 0 (preserving Carry Flag) + adc b ;; [1] | B += Carry + ld b, a ;; [1] | ;; A = *(BC + A) ld a, (bc) ;; [2] A = Value stored at the table pointed by BC .endm - ;; Convert newColor to pixel format (E) - ld a, h ;; [1] A = H new color index - convertPixel ;; [10] | Convert into A - ld e, a ;; [1] | E = A new color : Axxx Axxx + ;; Convert newColor to pixel format (E) + ld a, h ;; [1] A = H new color index + convertPixel ;; [10] | Convert into A + ld e, a ;; [1] | E = A new color : Axxx Axxx - ;; Convert oldColor to pixel format (D) - ld a, l ;; [1] A = L old color index - convertPixel ;; [10] | Convert into A - ld d, a ;; [1] | D = A old color : Axxx Axxx - - ld c, #0x88 ;; [2] C = First Mask to get pixel A : Axxx Axxx - exx ;; [1] Switch to Alternate registers - - ld__ixl_c ;; [1] IXL = C (Width) - ld c, b ;; [1] C = B (Height) - -convertLoop: - ld (startLine), de ;; [6] Store DE start line (DestMem) - ld__b_ixl ;; [2] B = IXL (Sprite Width) - + ;; Convert oldColor to pixel format (D) + ld a, l ;; [1] A = L old color index + convertPixel ;; [10] | Convert into A + ld d, a ;; [1] | D = A old color : Axxx Axxx + + ld c, #0x88 ;; [2] C = First Mask to get pixel A : Axxx Axxx + exx ;; [1] Switch to Alternate registers + + ld__ixl_c ;; [1] IXL = C (Width) + ld c, b ;; [1] C = B (Height) + +convertLoop: + ld (startLine), de ;; [6] Store DE start line (DestMem) + ld__b_ixl ;; [2] B = IXL (Sprite Width) + lineLoop: - inc hl ;; [2] Next byte sprite Color source - ld a, (hl) ;; [2] A = (HL) current Byte of sprite Color - dec hl ;; [2] Previous byte sprite Mask source - + inc hl ;; [2] Next byte sprite Color source + ld a, (hl) ;; [2] A = (HL) current Byte of sprite Color + dec hl ;; [2] Previous byte sprite Mask source + exx ;; [1] Switch to Default registers - - ld l, a ;; [1] L = A current Byte of sprite : ABCD ABCD - - and c ;; [2] A |= C (C = 0x88) : Axxx Axxx - - cp d ;; [1] Test if pixel (A) is the old colour to be replaced (D) - jr nz, readPixelA ;; [2/3] If not equal go to next pixel + + ld l, a ;; [1] L = A current Byte of sprite : ABCD ABCD + + and c ;; [2] A |= C (C = 0x88) : Axxx Axxx + + cp d ;; [1] Test if pixel (A) is the old colour to be replaced (D) + jr nz, readPixelA ;; [2/3] If not equal go to next pixel ld a, e ;; [1] else A = new colour to set (E) - + readPixelA: - ld h, a ;; [1] H = A (current colorized sprite) : Axxx Axxx - - sla l ;; [2] L (current byte of sprite) << 1 : ABCD ABCD -> BCDx BCDx - ld a, l ;; [1] A = L : BCDx BCDx - and c ;; [2] A |= Mask (0x88) : Bxxx Bxxx - - cp d ;; [1] Test if pixel (A) is the old colour to be replaced (D) - jr nz, readPixelB ;; [2/3] If not equal go to next pixel + ld h, a ;; [1] H = A (current colorized sprite) : Axxx Axxx + + sla l ;; [2] L (current byte of sprite) << 1 : ABCD ABCD -> BCDx BCDx + ld a, l ;; [1] A = L : BCDx BCDx + and c ;; [2] A |= Mask (0x88) : Bxxx Bxxx + + cp d ;; [1] Test if pixel (A) is the old colour to be replaced (D) + jr nz, readPixelB ;; [2/3] If not equal go to next pixel ld a, e ;; [1] else A = new colour to set (E) - + readPixelB: rrca ;; [1] A = Axxx Axxx >> 1 : xBxx xBxx - or h ;; [1] A |= H (color byte) : Axxx Axxx - ld h, a ;; [1] H = A : ABxx ABxx - - sla l ;; [2] L ( BCDx BCDx) << 1 : CDxx CDxx - ld a, l ;; [1] A = L : CDxx CDxx - and c ;; [1] A |= C (C = 0x88) : Cxxx Cxxx - - cp d ;; [1] Test if pixel (A) is the old colour to be replaced (D) - jr nz, readPixelC ;; [2/3] If not equal go to next pixel + or h ;; [1] A |= H (color byte) : Axxx Axxx + ld h, a ;; [1] H = A : ABxx ABxx + + sla l ;; [2] L ( BCDx BCDx) << 1 : CDxx CDxx + ld a, l ;; [1] A = L : CDxx CDxx + and c ;; [1] A |= C (C = 0x88) : Cxxx Cxxx + + cp d ;; [1] Test if pixel (A) is the old colour to be replaced (D) + jr nz, readPixelC ;; [2/3] If not equal go to next pixel ld a, e ;; [1] else A = new colour to set (E) - + readPixelC: - rrca ;; [1] A = Axxx Axxx >> 1 : xBxx xBxx - rrca ;; [1] A = xxCx xxCx << 1 : xxCx xxCx - or h ;; [1] A |= H (ABxx ABxx) : ABCx ABCx - ld h, a ;; [1] H = A : ABCx ABCx + rrca ;; [1] A = Axxx Axxx >> 1 : xBxx xBxx + rrca ;; [1] A = xxCx xxCx << 1 : xxCx xxCx + or h ;; [1] A |= H (ABxx ABxx) : ABCx ABCx + ld h, a ;; [1] H = A : ABCx ABCx - sla l ;; [2] L (BCDx BCDx) << 1 : Dxxx Dxxx - ld a, l ;; [1] A = L : Dxxx Dxxx - and c ;; [1] A |= C (C = 0x88) : Dxxx Dxxx - - cp d ;; [1] Test if pixel (A) is the old colour to be replaced (D) - jr nz, readPixelD ;; [2/3] If not equal go to next pixel + sla l ;; [2] L (BCDx BCDx) << 1 : Dxxx Dxxx + ld a, l ;; [1] A = L : Dxxx Dxxx + and c ;; [1] A |= C (C = 0x88) : Dxxx Dxxx + + cp d ;; [1] Test if pixel (A) is the old colour to be replaced (D) + jr nz, readPixelD ;; [2/3] If not equal go to next pixel ld a, e ;; [1] else A = new colour to set (E) - + readPixelD: - rrca ;; [1] A = Axxx Axxx >> 1 : xBxx xBxx - rrca ;; [1] A = xBxx xBxx >> 1 : xxCx xxCx - rrca ;; [1] A = xxCx xxxx >> 1 : xxxD xxxD - or h ;; [1] A |= H (ABCx ABCx) : ABCD ABCD + rrca ;; [1] A = Axxx Axxx >> 1 : xBxx xBxx + rrca ;; [1] A = xBxx xBxx >> 1 : xxCx xxCx + rrca ;; [1] A = xxCx xxxx >> 1 : xxxD xxxD + or h ;; [1] A |= H (ABCx ABCx) : ABCD ABCD - exx ;; [1] Switch to Alternate registers + exx ;; [1] Switch to Alternate registers drawByte: - ld (sprite_color), a ;; [4] sprite_color = A (Sprite Byte) - - ld a, (de) ;; [2] Get next background byte into A - and (hl) ;; [2] Erase background part that is to be overwritten (Mask step 1) - inc hl ;; [3] HL += 1 => Point HL to Sprite Colour information + ld (sprite_color), a ;; [4] sprite_color = A (Sprite Byte) + + ld a, (de) ;; [2] Get next background byte into A + and (hl) ;; [2] Erase background part that is to be overwritten (Mask step 1) + inc hl ;; [3] HL += 1 => Point HL to Sprite Colour information sprite_color = .+1 ;; Placeholder for the Sprite Color computed - or #00 ;; [2] Add up background and sprite information in one byte (Mask step 2) - ld (de), a ;; [2] Save modified background + sprite data information into memory - - inc hl ;; [2] Next byte sprite source - inc de ;; [2] Next byte Dest Memory - djnz lineLoop ;; [3] Decrement B (Width) if B != 0 goto lineLoop - - dec c ;; [1] Decrement C (Height) - jr z, end ;; [2/3] If C == O goto end + or #00 ;; [2] Add up background and sprite information in one byte (Mask step 2) + ld (de), a ;; [2] Save modified background + sprite data information into memory + + inc hl ;; [2] Next byte sprite source + inc de ;; [2] Next byte Dest Memory + djnz lineLoop ;; [3] Decrement B (Width) if B != 0 goto lineLoop + + dec c ;; [1] Decrement C (Height) + jr z, end ;; [2/3] If C == O goto end startLine = .+1 ;; Placeholder for the Start line adress - ld de, #0000 ;; [3] DE = Start Line + ld de, #0000 ;; [3] DE = Start Line ld a, d ;; [1] Start of next pixel line normally is 0x0800 bytes away. add #0x08 ;; [2] so we add it to DE (just by adding 0x08 to D) ld d, a ;; [1] - and #0x38 ;; [2] We check if we have crossed memory boundary (every 8 pixel lines).. - + and #0x38 ;; [2] We check if we have crossed memory boundary (every 8 pixel lines).. + jr nz, convertLoop ;; [2/3] .. by checking the 4 bits that identify present memory line. ;; .... If 0, we have crossed boundaries @@ -238,9 +238,9 @@ dms_sprite_8bit_boundary_crossed: ld a, d ;; [1] -- which effectively is the same as moving it 1 bank backwards and then adc #0xC0 ;; [2] -- 50 bytes forwards (which is what we want to move it to the next pixel line) ld d, a ;; [1] -- Calculations are made with 8 bit maths as it is faster than other alternatives here - - jr convertLoop ;; [3] Jump to continue with next pixel line + + jr convertLoop ;; [3] Jump to continue with next pixel line end: - ;; Return is included in bindings - + ;; Return is included in bindings + diff --git a/cpctelera/src/sprites/colorReplace/M1/cpct_drawSpriteMaskedColorizeM1_asmbindings.s b/cpctelera/src/sprites/colorReplace/M1/cpct_drawSpriteMaskedColorizeM1_asmbindings.s index b8b2ce518..33d3dd82a 100644 --- a/cpctelera/src/sprites/colorReplace/M1/cpct_drawSpriteMaskedColorizeM1_asmbindings.s +++ b/cpctelera/src/sprites/colorReplace/M1/cpct_drawSpriteMaskedColorizeM1_asmbindings.s @@ -1,7 +1,7 @@ ;;-----------------------------LICENSE NOTICE------------------------------------ ;; This file is part of CPCtelera: An Amstrad CPC Game Engine -;; Copyright (C) 2017 Arnaud Bouche (Arnaud6128) -;; Copyright (C) 2017 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) +;; Copyright (C) 2018 Arnaud Bouche (@Arnaud6128) +;; Copyright (C) 2018 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) ;; ;; This program is free software: you can redistribute it and/or modify ;; it under the terms of the GNU Lesser General Public License as published by diff --git a/cpctelera/src/sprites/colorReplace/M1/cpct_drawSpriteMaskedColorizeM1_cbindings.s b/cpctelera/src/sprites/colorReplace/M1/cpct_drawSpriteMaskedColorizeM1_cbindings.s index 2c68ccd2b..abc535c5c 100644 --- a/cpctelera/src/sprites/colorReplace/M1/cpct_drawSpriteMaskedColorizeM1_cbindings.s +++ b/cpctelera/src/sprites/colorReplace/M1/cpct_drawSpriteMaskedColorizeM1_cbindings.s @@ -1,7 +1,7 @@ ;;-----------------------------LICENSE NOTICE------------------------------------ ;; This file is part of CPCtelera: An Amstrad CPC Game Engine -;; Copyright (C) 2017 Arnaud Bouche (Arnaud6128) -;; Copyright (C) 2017 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) +;; Copyright (C) 2018 Arnaud Bouche (@Arnaud6128) +;; Copyright (C) 2018 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) ;; ;; This program is free software: you can redistribute it and/or modify ;; it under the terms of the GNU Lesser General Public License as published by diff --git a/cpctelera/src/sprites/colorReplace/M1/cpct_spriteColorizeM1.asm b/cpctelera/src/sprites/colorReplace/M1/cpct_spriteColorizeM1.asm index be64dd10b..282449e43 100644 --- a/cpctelera/src/sprites/colorReplace/M1/cpct_spriteColorizeM1.asm +++ b/cpctelera/src/sprites/colorReplace/M1/cpct_spriteColorizeM1.asm @@ -1,7 +1,7 @@ ;;-----------------------------LICENSE NOTICE------------------------------------ ;; This file is part of CPCtelera: An Amstrad CPC Game Engine -;; Copyright (C) 2017 Arnaud Bouche (Arnaud6128) -;; Copyright (C) 2017 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) +;; Copyright (C) 2018 Arnaud Bouche (@Arnaud6128) +;; Copyright (C) 2018 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) ;; ;; This program is free software: you can redistribute it and/or modify ;; it under the terms of the GNU Lesser General Public License as published by @@ -88,107 +88,107 @@ .globl dc_mode1_ct ;; Macro to convert color to pixel Mode1 : Axxx Axxx -.macro convertPixel ;; From cpct_px2byteM1 - ld bc, #dc_mode1_ct ;; [3] BC points to conversion table (dc_mode1_ct) - - ;; Compute HL += A - add c ;; [1] | C += A - ld c, a ;; [1] | - sub a ;; [1] A = 0 (preserving Carry Flag) - adc b ;; [1] | L += Carry - ld b, a ;; [1] | +.macro convertPixel ;; From cpct_px2byteM1 + ld bc, #dc_mode1_ct ;; [3] BC points to conversion table (dc_mode1_ct) + + ;; Compute HL += A + add c ;; [1] | C += A + ld c, a ;; [1] | + sub a ;; [1] A = 0 (preserving Carry Flag) + adc b ;; [1] | L += Carry + ld b, a ;; [1] | ;; A = *(BC + A) ld a, (bc) ;; [2] A = Value stored at the table pointed by BC .endm - ;; Convert newColor to pixel format (E) - ld a, h ;; [1] A = H new color index - convertPixel ;; [10] | Convert into A - ld e, a ;; [1] | E = A new color : Axxx Axxx + ;; Convert newColor to pixel format (E) + ld a, h ;; [1] A = H new color index + convertPixel ;; [10] | Convert into A + ld e, a ;; [1] | E = A new color : Axxx Axxx - ;; Convert oldColor to pixel format (D) - ld a, l ;; [1] A = L old color index - convertPixel ;; [10] | Convert into A - ld d, a ;; [1] | D = A old color : Axxx Axxx - - ld c, #0x88 ;; [2] C = First Mask to get pixel A : Axxx Axxx - - exx ;; [1] Switch to Alternate registers - - ld__ixl_c ;; [1] IXL = C (Width) - ld c, b ;; [1] C = B (Height) - -convertLoop: - ld__b_ixl ;; [2] B = IXL (Sprite Width) - + ;; Convert oldColor to pixel format (D) + ld a, l ;; [1] A = L old color index + convertPixel ;; [10] | Convert into A + ld d, a ;; [1] | D = A old color : Axxx Axxx + + ld c, #0x88 ;; [2] C = First Mask to get pixel A : Axxx Axxx + + exx ;; [1] Switch to Alternate registers + + ld__ixl_c ;; [1] IXL = C (Width) + ld c, b ;; [1] C = B (Height) + +convertLoop: + ld__b_ixl ;; [2] B = IXL (Sprite Width) + lineLoop: - ld a, (hl) ;; [2] A = (HL) current Byte of sprite + ld a, (hl) ;; [2] A = (HL) current Byte of sprite exx ;; [1] Switch to Default registers - - ld l, a ;; [1] L = A current Byte of sprite : ABCD ABCD - and c ;; [2] A |= C (C = 0x88) : Axxx Axxx - - cp d ;; [1] Test if pixel (A) is the old colour to be replaced (D) - jr nz, readPixelA ;; [2/3] If not equal go to next pixel + + ld l, a ;; [1] L = A current Byte of sprite : ABCD ABCD + and c ;; [2] A |= C (C = 0x88) : Axxx Axxx + + cp d ;; [1] Test if pixel (A) is the old colour to be replaced (D) + jr nz, readPixelA ;; [2/3] If not equal go to next pixel ld a, e ;; [1] else A = new colour to set (E) - + readPixelA: - ld h, a ;; [1] H = A (current colorized sprite) : Axxx Axxx - - sla l ;; [2] L (current byte of sprite) << 1 : ABCD ABCD -> BCDx BCDx - ld a, l ;; [1] A = L : BCDx BCDx - and c ;; [2] A |= Mask (0x88) : Bxxx Bxxx - - cp d ;; [1] Test if pixel (A) is the old colour to be replaced (D) - jr nz, readPixelB ;; [2/3] If not equal go to next pixel + ld h, a ;; [1] H = A (current colorized sprite) : Axxx Axxx + + sla l ;; [2] L (current byte of sprite) << 1 : ABCD ABCD -> BCDx BCDx + ld a, l ;; [1] A = L : BCDx BCDx + and c ;; [2] A |= Mask (0x88) : Bxxx Bxxx + + cp d ;; [1] Test if pixel (A) is the old colour to be replaced (D) + jr nz, readPixelB ;; [2/3] If not equal go to next pixel ld a, e ;; [1] else A = new colour to set (E) - + readPixelB: rrca ;; [1] A = Axxx Axxx >> 1 : xBxx xBxx - or h ;; [1] A |= H (color byte) : Axxx Axxx - ld h, a ;; [1] H = A : ABxx ABxx - - sla l ;; [2] L ( BCDx BCDx) << 1 : CDxx CDxx - ld a, l ;; [1] A = L : CDxx CDxx - and c ;; [1] A |= C (C = 0x88) : Cxxx Cxxx - - cp d ;; [1] Test if pixel (A) is the old colour to be replaced (D) - jr nz, readPixelC ;; [2/3] If not equal go to next pixel + or h ;; [1] A |= H (color byte) : Axxx Axxx + ld h, a ;; [1] H = A : ABxx ABxx + + sla l ;; [2] L ( BCDx BCDx) << 1 : CDxx CDxx + ld a, l ;; [1] A = L : CDxx CDxx + and c ;; [1] A |= C (C = 0x88) : Cxxx Cxxx + + cp d ;; [1] Test if pixel (A) is the old colour to be replaced (D) + jr nz, readPixelC ;; [2/3] If not equal go to next pixel ld a, e ;; [1] else A = new colour to set (E) - + readPixelC: - rrca ;; [1] A = Axxx Axxx >> 1 : xBxx xBxx - rrca ;; [1] A = xxCx xxCx << 1 : xxCx xxCx - or h ;; [1] A |= H (ABxx ABxx) : ABCx ABCx - ld h, a ;; [1] H = A : ABCx ABCx + rrca ;; [1] A = Axxx Axxx >> 1 : xBxx xBxx + rrca ;; [1] A = xxCx xxCx << 1 : xxCx xxCx + or h ;; [1] A |= H (ABxx ABxx) : ABCx ABCx + ld h, a ;; [1] H = A : ABCx ABCx - sla l ;; [2] L (BCDx BCDx) << 1 : Dxxx Dxxx - ld a, l ;; [1] A = L : Dxxx Dxxx - and c ;; [1] A |= C (C = 0x88) : Dxxx Dxxx - - cp d ;; [1] Test if pixel (A) is the old colour to be replaced (D) - jr nz, readPixelD ;; [2/3] If not equal go to next pixel + sla l ;; [2] L (BCDx BCDx) << 1 : Dxxx Dxxx + ld a, l ;; [1] A = L : Dxxx Dxxx + and c ;; [1] A |= C (C = 0x88) : Dxxx Dxxx + + cp d ;; [1] Test if pixel (A) is the old colour to be replaced (D) + jr nz, readPixelD ;; [2/3] If not equal go to next pixel ld a, e ;; [1] else A = new colour to set (E) - + readPixelD: - rrca ;; [1] A = Axxx Axxx >> 1 : xBxx xBxx - rrca ;; [1] A = xBxx xBxx >> 1 : xxCx xxCx - rrca ;; [1] A = xxCx xxxx >> 1 : xxxD xxxD - or h ;; [1] A |= H (ABCx ABCx) : ABCD ABCD + rrca ;; [1] A = Axxx Axxx >> 1 : xBxx xBxx + rrca ;; [1] A = xBxx xBxx >> 1 : xxCx xxCx + rrca ;; [1] A = xxCx xxxx >> 1 : xxxD xxxD + or h ;; [1] A |= H (ABCx ABCx) : ABCD ABCD setByte: - exx ;; [1] Switch to Alternate registers + exx ;; [1] Switch to Alternate registers - ld (de), a ;; [2] Update current sprite byte with pixels - inc hl ;; [2] Next byte sprite source - inc de ;; [2] Next byte sprite colorized - djnz lineLoop ;; [3] Decrement B (Width) if != 0 goto lineLoop - -nextLine: - dec c ;; [1] Decrement C (Height) - jr nz, convertLoop ;; [2/3] If != O goto convertLoop - + ld (de), a ;; [2] Update current sprite byte with pixels + inc hl ;; [2] Next byte sprite source + inc de ;; [2] Next byte sprite colorized + djnz lineLoop ;; [3] Decrement B (Width) if != 0 goto lineLoop + +nextLine: + dec c ;; [1] Decrement C (Height) + jr nz, convertLoop ;; [2/3] If != O goto convertLoop + end: - ;; Return is included in bindings - + ;; Return is included in bindings + diff --git a/cpctelera/src/sprites/colorReplace/M1/cpct_spriteColorizeM1_asmbindings.s b/cpctelera/src/sprites/colorReplace/M1/cpct_spriteColorizeM1_asmbindings.s index 1de96a3fa..b4902424a 100644 --- a/cpctelera/src/sprites/colorReplace/M1/cpct_spriteColorizeM1_asmbindings.s +++ b/cpctelera/src/sprites/colorReplace/M1/cpct_spriteColorizeM1_asmbindings.s @@ -1,7 +1,7 @@ ;;-----------------------------LICENSE NOTICE------------------------------------ ;; This file is part of CPCtelera: An Amstrad CPC Game Engine -;; Copyright (C) 2017 Arnaud Bouche (Arnaud6128) -;; Copyright (C) 2017 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) +;; Copyright (C) 2018 Arnaud Bouche (@Arnaud6128) +;; Copyright (C) 2018 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) ;; ;; This program is free software: you can redistribute it and/or modify ;; it under the terms of the GNU Lesser General Public License as published by diff --git a/cpctelera/src/sprites/colorReplace/M1/cpct_spriteColorizeM1_cbindings.s b/cpctelera/src/sprites/colorReplace/M1/cpct_spriteColorizeM1_cbindings.s index c7cb8916f..911a3fd0c 100644 --- a/cpctelera/src/sprites/colorReplace/M1/cpct_spriteColorizeM1_cbindings.s +++ b/cpctelera/src/sprites/colorReplace/M1/cpct_spriteColorizeM1_cbindings.s @@ -1,7 +1,7 @@ ;;-----------------------------LICENSE NOTICE------------------------------------ ;; This file is part of CPCtelera: An Amstrad CPC Game Engine -;; Copyright (C) 2017 Arnaud Bouche (Arnaud6128) -;; Copyright (C) 2017 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) +;; Copyright (C) 2018 Arnaud Bouche (@Arnaud6128) +;; Copyright (C) 2018 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) ;; ;; This program is free software: you can redistribute it and/or modify ;; it under the terms of the GNU Lesser General Public License as published by diff --git a/cpctelera/src/sprites/colorReplace/M1/cpct_spriteMaskedColorizeM1.asm b/cpctelera/src/sprites/colorReplace/M1/cpct_spriteMaskedColorizeM1.asm index c135f3fa7..2da556b00 100644 --- a/cpctelera/src/sprites/colorReplace/M1/cpct_spriteMaskedColorizeM1.asm +++ b/cpctelera/src/sprites/colorReplace/M1/cpct_spriteMaskedColorizeM1.asm @@ -1,7 +1,7 @@ ;;-----------------------------LICENSE NOTICE------------------------------------ ;; This file is part of CPCtelera: An Amstrad CPC Game Engine -;; Copyright (C) 2017 Arnaud Bouche (Arnaud6128) -;; Copyright (C) 2017 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) +;; Copyright (C) 2018 Arnaud Bouche (@Arnaud6128) +;; Copyright (C) 2018 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) ;; ;; This program is free software: you can redistribute it and/or modify ;; it under the terms of the GNU Lesser General Public License as published by @@ -94,112 +94,112 @@ .globl dc_mode1_ct ;; Macro to convert color to pixel Mode1 : Axxx Axxx -.macro convertPixel ;; From cpct_px2byteM1 - ld bc, #dc_mode1_ct ;; [3] HL points to conversion table (dc_mode1_ct) - - ;; Compute HL += A - add c ;; [1] | L += A - ld c, a ;; [1] | - sub a ;; [1] A = 0 (preserving Carry Flag) - adc b ;; [1] | H += Carry - ld b, a ;; [1] | +.macro convertPixel ;; From cpct_px2byteM1 + ld bc, #dc_mode1_ct ;; [3] HL points to conversion table (dc_mode1_ct) + + ;; Compute HL += A + add c ;; [1] | L += A + ld c, a ;; [1] | + sub a ;; [1] A = 0 (preserving Carry Flag) + adc b ;; [1] | H += Carry + ld b, a ;; [1] | ;; A = *(HL + A) ld a, (bc) ;; [2] A = Value stored at the table pointed by HL .endm - ;; Convert newColor to pixel format (E) - ld a, h ;; [1] A = H new color index - convertPixel ;; [10] | Convert into A - ld e, a ;; [1] | E = A new color : Axxx Axxx + ;; Convert newColor to pixel format (E) + ld a, h ;; [1] A = H new color index + convertPixel ;; [10] | Convert into A + ld e, a ;; [1] | E = A new color : Axxx Axxx - ;; Convert oldColor to pixel format (D) - ld a, l ;; [1] A = L old color index - convertPixel ;; [10] | Convert into A - ld d, a ;; [1] | D = A old color : Axxx Axxx - - ld c, #0x88 ;; [2] C = First Mask to get pixel A : Axxx Axxx - - exx ;; [1] Switch to Alternate registers - - ld__ixl_c ;; [1] IXL = C (Width) - ld c, b ;; [1] C = B (Height) - -convertLoop: - ld__b_ixl ;; [2] B = IXL (Sprite Width) - + ;; Convert oldColor to pixel format (D) + ld a, l ;; [1] A = L old color index + convertPixel ;; [10] | Convert into A + ld d, a ;; [1] | D = A old color : Axxx Axxx + + ld c, #0x88 ;; [2] C = First Mask to get pixel A : Axxx Axxx + + exx ;; [1] Switch to Alternate registers + + ld__ixl_c ;; [1] IXL = C (Width) + ld c, b ;; [1] C = B (Height) + +convertLoop: + ld__b_ixl ;; [2] B = IXL (Sprite Width) + lineLoop: - ld a, (hl) ;; [2] A = (HL) current Byte of sprite Mask - ld (de), a ;; [2] (DE) = A Copy of sprite Mask - inc hl ;; [2] Next byte sprite Color source - inc de ;; [2] Next byte sprite Color destination - ld a, (hl) ;; [2] A = (HL) current Byte of sprite Color - + ld a, (hl) ;; [2] A = (HL) current Byte of sprite Mask + ld (de), a ;; [2] (DE) = A Copy of sprite Mask + inc hl ;; [2] Next byte sprite Color source + inc de ;; [2] Next byte sprite Color destination + ld a, (hl) ;; [2] A = (HL) current Byte of sprite Color + exx ;; [1] Switch to Default registers - - ld l, a ;; [1] L = A current Byte of sprite : ABCD ABCD - - and c ;; [2] A |= C (C = 0x88) : Axxx Axxx - - cp d ;; [1] Test if pixel (A) is the old colour to be replaced (D) - jr nz, readPixelA ;; [2/3] If not equal go to next pixel + + ld l, a ;; [1] L = A current Byte of sprite : ABCD ABCD + + and c ;; [2] A |= C (C = 0x88) : Axxx Axxx + + cp d ;; [1] Test if pixel (A) is the old colour to be replaced (D) + jr nz, readPixelA ;; [2/3] If not equal go to next pixel ld a, e ;; [1] else A = new colour to set (E) - + readPixelA: - ld h, a ;; [1] H = A (current colorized sprite) : Axxx Axxx - - sla l ;; [2] L (current byte of sprite) << 1 : ABCD ABCD -> BCDx BCDx - ld a, l ;; [1] A = L : BCDx BCDx - and c ;; [2] A |= Mask (0x88) : Bxxx Bxxx - - cp d ;; [1] Test if pixel (A) is the old colour to be replaced (D) - jr nz, readPixelB ;; [2/3] If not equal go to next pixel + ld h, a ;; [1] H = A (current colorized sprite) : Axxx Axxx + + sla l ;; [2] L (current byte of sprite) << 1 : ABCD ABCD -> BCDx BCDx + ld a, l ;; [1] A = L : BCDx BCDx + and c ;; [2] A |= Mask (0x88) : Bxxx Bxxx + + cp d ;; [1] Test if pixel (A) is the old colour to be replaced (D) + jr nz, readPixelB ;; [2/3] If not equal go to next pixel ld a, e ;; [1] else A = new colour to set (E) - + readPixelB: rrca ;; [1] A = Axxx Axxx >> 1 : xBxx xBxx - or h ;; [1] A |= H (color byte) : Axxx Axxx - ld h, a ;; [1] H = A : ABxx ABxx - - sla l ;; [2] L ( BCDx BCDx) << 1 : CDxx CDxx - ld a, l ;; [1] A = L : CDxx CDxx - and c ;; [1] A |= C (C = 0x88) : Cxxx Cxxx - - cp d ;; [1] Test if pixel (A) is the old colour to be replaced (D) - jr nz, readPixelC ;; [2/3] If not equal go to next pixel + or h ;; [1] A |= H (color byte) : Axxx Axxx + ld h, a ;; [1] H = A : ABxx ABxx + + sla l ;; [2] L ( BCDx BCDx) << 1 : CDxx CDxx + ld a, l ;; [1] A = L : CDxx CDxx + and c ;; [1] A |= C (C = 0x88) : Cxxx Cxxx + + cp d ;; [1] Test if pixel (A) is the old colour to be replaced (D) + jr nz, readPixelC ;; [2/3] If not equal go to next pixel ld a, e ;; [1] else A = new colour to set (E) - + readPixelC: - rrca ;; [1] A = Axxx Axxx >> 1 : xBxx xBxx - rrca ;; [1] A = xxCx xxCx << 1 : xxCx xxCx - or h ;; [1] A |= H (ABxx ABxx) : ABCx ABCx - ld h, a ;; [1] H = A : ABCx ABCx + rrca ;; [1] A = Axxx Axxx >> 1 : xBxx xBxx + rrca ;; [1] A = xxCx xxCx << 1 : xxCx xxCx + or h ;; [1] A |= H (ABxx ABxx) : ABCx ABCx + ld h, a ;; [1] H = A : ABCx ABCx - sla l ;; [2] L (BCDx BCDx) << 1 : Dxxx Dxxx - ld a, l ;; [1] A = L : Dxxx Dxxx - and c ;; [1] A |= C (C = 0x88) : Dxxx Dxxx - - cp d ;; [1] Test if pixel (A) is the old colour to be replaced (D) - jr nz, readPixelD ;; [2/3] If not equal go to next pixel + sla l ;; [2] L (BCDx BCDx) << 1 : Dxxx Dxxx + ld a, l ;; [1] A = L : Dxxx Dxxx + and c ;; [1] A |= C (C = 0x88) : Dxxx Dxxx + + cp d ;; [1] Test if pixel (A) is the old colour to be replaced (D) + jr nz, readPixelD ;; [2/3] If not equal go to next pixel ld a, e ;; [1] else A = new colour to set (E) - + readPixelD: - rrca ;; [1] A = Axxx Axxx >> 1 : xBxx xBxx - rrca ;; [1] A = xBxx xBxx >> 1 : xxCx xxCx - rrca ;; [1] A = xxCx xxxx >> 1 : xxxD xxxD - or h ;; [1] A |= H (ABCx ABCx) : ABCD ABCD + rrca ;; [1] A = Axxx Axxx >> 1 : xBxx xBxx + rrca ;; [1] A = xBxx xBxx >> 1 : xxCx xxCx + rrca ;; [1] A = xxCx xxxx >> 1 : xxxD xxxD + or h ;; [1] A |= H (ABCx ABCx) : ABCD ABCD -setByte: - exx ;; [1] Switch to Alternate registers +setByte: + exx ;; [1] Switch to Alternate registers - ld (de), a ;; [2] Update current sprite byte with pixels - inc hl ;; [2] Next byte sprite source - inc de ;; [2] Next byte sprite colorized - djnz lineLoop ;; [3] Decrement B (Width) if != 0 goto lineLoop - -nextLine: - dec c ;; [1] Decrement C (Height) - jr nz, convertLoop ;; [2/3] If != O goto convertLoop - + ld (de), a ;; [2] Update current sprite byte with pixels + inc hl ;; [2] Next byte sprite source + inc de ;; [2] Next byte sprite colorized + djnz lineLoop ;; [3] Decrement B (Width) if != 0 goto lineLoop + +nextLine: + dec c ;; [1] Decrement C (Height) + jr nz, convertLoop ;; [2/3] If != O goto convertLoop + end: - ;; Return is included in bindings \ No newline at end of file + ;; Return is included in bindings \ No newline at end of file diff --git a/cpctelera/src/sprites/colorReplace/M1/cpct_spriteMaskedColorizeM1_asmbindings.s b/cpctelera/src/sprites/colorReplace/M1/cpct_spriteMaskedColorizeM1_asmbindings.s index 6119b9763..337270684 100644 --- a/cpctelera/src/sprites/colorReplace/M1/cpct_spriteMaskedColorizeM1_asmbindings.s +++ b/cpctelera/src/sprites/colorReplace/M1/cpct_spriteMaskedColorizeM1_asmbindings.s @@ -1,7 +1,7 @@ ;;-----------------------------LICENSE NOTICE------------------------------------ ;; This file is part of CPCtelera: An Amstrad CPC Game Engine -;; Copyright (C) 2017 Arnaud Bouche (Arnaud6128) -;; Copyright (C) 2017 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) +;; Copyright (C) 2018 Arnaud Bouche (@Arnaud6128) +;; Copyright (C) 2018 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) ;; ;; This program is free software: you can redistribute it and/or modify ;; it under the terms of the GNU Lesser General Public License as published by diff --git a/cpctelera/src/sprites/colorReplace/M1/cpct_spriteMaskedColorizeM1_cbindings.s b/cpctelera/src/sprites/colorReplace/M1/cpct_spriteMaskedColorizeM1_cbindings.s index 8592b429f..871930f81 100644 --- a/cpctelera/src/sprites/colorReplace/M1/cpct_spriteMaskedColorizeM1_cbindings.s +++ b/cpctelera/src/sprites/colorReplace/M1/cpct_spriteMaskedColorizeM1_cbindings.s @@ -1,7 +1,7 @@ ;;-----------------------------LICENSE NOTICE------------------------------------ ;; This file is part of CPCtelera: An Amstrad CPC Game Engine -;; Copyright (C) 2017 Arnaud Bouche (Arnaud6128) -;; Copyright (C) 2017 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) +;; Copyright (C) 2018 Arnaud Bouche (@Arnaud6128) +;; Copyright (C) 2018 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) ;; ;; This program is free software: you can redistribute it and/or modify ;; it under the terms of the GNU Lesser General Public License as published by From 74f3eaa1fbaab2101edbe21b77b622df44ca8c68 Mon Sep 17 00:00:00 2001 From: ronaldo <ronaldo@cheesetea.com> Date: Fri, 26 Jan 2018 21:46:15 +0100 Subject: [PATCH 21/31] Better include form for cpct_undocumentedOpcodes * Root cpctelera/src folder is added to include folders --- .../colorReplace/M0/cpct_drawSpriteColorizeM0_asmbindings.s | 2 +- .../colorReplace/M0/cpct_drawSpriteColorizeM0_cbindings.s | 2 +- .../M0/cpct_drawSpriteMaskedAlignedColorizeM0_asmbindings.s | 2 +- .../M0/cpct_drawSpriteMaskedAlignedColorizeM0_cbindings.s | 2 +- .../M0/cpct_drawSpriteMaskedColorizeM0_asmbindings.s | 2 +- .../colorReplace/M0/cpct_drawSpriteMaskedColorizeM0_cbindings.s | 2 +- .../sprites/colorReplace/M0/cpct_spriteColorizeM0_asmbindings.s | 2 +- .../sprites/colorReplace/M0/cpct_spriteColorizeM0_cbindings.s | 2 +- .../colorReplace/M0/cpct_spriteMaskedColorizeM0_asmbindings.s | 2 +- .../colorReplace/M0/cpct_spriteMaskedColorizeM0_cbindings.s | 2 +- .../colorReplace/M1/cpct_drawSpriteColorizeM1_asmbindings.s | 2 +- .../colorReplace/M1/cpct_drawSpriteColorizeM1_cbindings.s | 2 +- .../M1/cpct_drawSpriteMaskedAlignedColorizeM1_asmbindings.s | 2 +- .../M1/cpct_drawSpriteMaskedAlignedColorizeM1_cbindings.s | 2 +- .../M1/cpct_drawSpriteMaskedColorizeM1_asmbindings.s | 2 +- .../colorReplace/M1/cpct_drawSpriteMaskedColorizeM1_cbindings.s | 2 +- .../sprites/colorReplace/M1/cpct_spriteColorizeM1_asmbindings.s | 2 +- .../sprites/colorReplace/M1/cpct_spriteColorizeM1_cbindings.s | 2 +- .../colorReplace/M1/cpct_spriteMaskedColorizeM1_asmbindings.s | 2 +- .../colorReplace/M1/cpct_spriteMaskedColorizeM1_cbindings.s | 2 +- 20 files changed, 20 insertions(+), 20 deletions(-) diff --git a/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteColorizeM0_asmbindings.s b/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteColorizeM0_asmbindings.s index 073609b70..cf824588a 100644 --- a/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteColorizeM0_asmbindings.s +++ b/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteColorizeM0_asmbindings.s @@ -18,7 +18,7 @@ ;;------------------------------------------------------------------------------- .module cpct_sprites -.include "../../../macros/cpct_undocumentedOpcodes.h.s" +.include "macros/cpct_undocumentedOpcodes.h.s" ;; ;; ASM bindings for <cpct_drawSpriteColorizeM0> diff --git a/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteColorizeM0_cbindings.s b/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteColorizeM0_cbindings.s index f4ad4b2f5..0f273f27c 100644 --- a/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteColorizeM0_cbindings.s +++ b/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteColorizeM0_cbindings.s @@ -18,7 +18,7 @@ ;;------------------------------------------------------------------------------- .module cpct_sprites -.include "../../../macros/cpct_undocumentedOpcodes.h.s" +.include "macros/cpct_undocumentedOpcodes.h.s" ;; ;; C bindings for <cpct_drawSpriteColorizeM0> diff --git a/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteMaskedAlignedColorizeM0_asmbindings.s b/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteMaskedAlignedColorizeM0_asmbindings.s index f566e8fc5..12697cf2f 100644 --- a/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteMaskedAlignedColorizeM0_asmbindings.s +++ b/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteMaskedAlignedColorizeM0_asmbindings.s @@ -18,7 +18,7 @@ ;;------------------------------------------------------------------------------- .module cpct_sprites -.include "../../../macros/cpct_undocumentedOpcodes.h.s" +.include "macros/cpct_undocumentedOpcodes.h.s" ;; ;; ASM bindings for <cpct_drawSpriteMaskedAlignedColorizeM0> diff --git a/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteMaskedAlignedColorizeM0_cbindings.s b/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteMaskedAlignedColorizeM0_cbindings.s index f8953c60b..3e9a1ed13 100644 --- a/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteMaskedAlignedColorizeM0_cbindings.s +++ b/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteMaskedAlignedColorizeM0_cbindings.s @@ -18,7 +18,7 @@ ;;------------------------------------------------------------------------------- .module cpct_sprites -.include "../../../macros/cpct_undocumentedOpcodes.h.s" +.include "macros/cpct_undocumentedOpcodes.h.s" ;; ;; C bindings for <cpct_drawSpriteMaskedAlignedColorizeM0> diff --git a/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteMaskedColorizeM0_asmbindings.s b/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteMaskedColorizeM0_asmbindings.s index 48bc1ef3c..17aa2495b 100644 --- a/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteMaskedColorizeM0_asmbindings.s +++ b/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteMaskedColorizeM0_asmbindings.s @@ -18,7 +18,7 @@ ;;------------------------------------------------------------------------------- .module cpct_sprites -.include "../../../macros/cpct_undocumentedOpcodes.h.s" +.include "macros/cpct_undocumentedOpcodes.h.s" ;; ;; ASM bindings for <cpct_drawSpriteMaskedColorizeM0> diff --git a/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteMaskedColorizeM0_cbindings.s b/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteMaskedColorizeM0_cbindings.s index 18f336eb5..a9cc0cb72 100644 --- a/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteMaskedColorizeM0_cbindings.s +++ b/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteMaskedColorizeM0_cbindings.s @@ -18,7 +18,7 @@ ;;------------------------------------------------------------------------------- .module cpct_sprites -.include "../../../macros/cpct_undocumentedOpcodes.h.s" +.include "macros/cpct_undocumentedOpcodes.h.s" ;; ;; C bindings for <cpct_drawSpriteMaskedColorizeM0> diff --git a/cpctelera/src/sprites/colorReplace/M0/cpct_spriteColorizeM0_asmbindings.s b/cpctelera/src/sprites/colorReplace/M0/cpct_spriteColorizeM0_asmbindings.s index 3339b8ea5..7e0c605f6 100644 --- a/cpctelera/src/sprites/colorReplace/M0/cpct_spriteColorizeM0_asmbindings.s +++ b/cpctelera/src/sprites/colorReplace/M0/cpct_spriteColorizeM0_asmbindings.s @@ -18,7 +18,7 @@ ;;------------------------------------------------------------------------------- .module cpct_sprites -.include "../../../macros/cpct_undocumentedOpcodes.h.s" +.include "macros/cpct_undocumentedOpcodes.h.s" ;; ;; ASM bindings for <cpct_spriteColorizeM0> diff --git a/cpctelera/src/sprites/colorReplace/M0/cpct_spriteColorizeM0_cbindings.s b/cpctelera/src/sprites/colorReplace/M0/cpct_spriteColorizeM0_cbindings.s index 27d164918..55fb9fa68 100644 --- a/cpctelera/src/sprites/colorReplace/M0/cpct_spriteColorizeM0_cbindings.s +++ b/cpctelera/src/sprites/colorReplace/M0/cpct_spriteColorizeM0_cbindings.s @@ -18,7 +18,7 @@ ;;------------------------------------------------------------------------------- .module cpct_sprites -.include "../../../macros/cpct_undocumentedOpcodes.h.s" +.include "macros/cpct_undocumentedOpcodes.h.s" ;; ;; C bindings for <cpct_spriteColorizeM0> diff --git a/cpctelera/src/sprites/colorReplace/M0/cpct_spriteMaskedColorizeM0_asmbindings.s b/cpctelera/src/sprites/colorReplace/M0/cpct_spriteMaskedColorizeM0_asmbindings.s index 04b8fcf88..c95fedf88 100644 --- a/cpctelera/src/sprites/colorReplace/M0/cpct_spriteMaskedColorizeM0_asmbindings.s +++ b/cpctelera/src/sprites/colorReplace/M0/cpct_spriteMaskedColorizeM0_asmbindings.s @@ -18,7 +18,7 @@ ;;------------------------------------------------------------------------------- .module cpct_sprites -.include "../../../macros/cpct_undocumentedOpcodes.h.s" +.include "macros/cpct_undocumentedOpcodes.h.s" ;; ;; ASM bindings for <cpct_spriteMaskedColorizeM0> diff --git a/cpctelera/src/sprites/colorReplace/M0/cpct_spriteMaskedColorizeM0_cbindings.s b/cpctelera/src/sprites/colorReplace/M0/cpct_spriteMaskedColorizeM0_cbindings.s index 3dad1ae84..0d7b9088d 100644 --- a/cpctelera/src/sprites/colorReplace/M0/cpct_spriteMaskedColorizeM0_cbindings.s +++ b/cpctelera/src/sprites/colorReplace/M0/cpct_spriteMaskedColorizeM0_cbindings.s @@ -18,7 +18,7 @@ ;;------------------------------------------------------------------------------- .module cpct_sprites -.include "../../../macros/cpct_undocumentedOpcodes.h.s" +.include "macros/cpct_undocumentedOpcodes.h.s" ;; ;; C bindings for <cpct_spriteMaskedColorizeM0> diff --git a/cpctelera/src/sprites/colorReplace/M1/cpct_drawSpriteColorizeM1_asmbindings.s b/cpctelera/src/sprites/colorReplace/M1/cpct_drawSpriteColorizeM1_asmbindings.s index 334f8da86..cf9a0b239 100644 --- a/cpctelera/src/sprites/colorReplace/M1/cpct_drawSpriteColorizeM1_asmbindings.s +++ b/cpctelera/src/sprites/colorReplace/M1/cpct_drawSpriteColorizeM1_asmbindings.s @@ -18,7 +18,7 @@ ;;------------------------------------------------------------------------------- .module cpct_sprites -.include "../../../macros/cpct_undocumentedOpcodes.h.s" +.include "macros/cpct_undocumentedOpcodes.h.s" ;; ;; ASM bindings for <cpct_drawSpriteColorizeM1> diff --git a/cpctelera/src/sprites/colorReplace/M1/cpct_drawSpriteColorizeM1_cbindings.s b/cpctelera/src/sprites/colorReplace/M1/cpct_drawSpriteColorizeM1_cbindings.s index 32ef19867..b7908d4f7 100644 --- a/cpctelera/src/sprites/colorReplace/M1/cpct_drawSpriteColorizeM1_cbindings.s +++ b/cpctelera/src/sprites/colorReplace/M1/cpct_drawSpriteColorizeM1_cbindings.s @@ -18,7 +18,7 @@ ;;------------------------------------------------------------------------------- .module cpct_sprites -.include "../../../macros/cpct_undocumentedOpcodes.h.s" +.include "macros/cpct_undocumentedOpcodes.h.s" ;; ;; C bindings for <cpct_drawSpriteColorizeM1> diff --git a/cpctelera/src/sprites/colorReplace/M1/cpct_drawSpriteMaskedAlignedColorizeM1_asmbindings.s b/cpctelera/src/sprites/colorReplace/M1/cpct_drawSpriteMaskedAlignedColorizeM1_asmbindings.s index 26f317d9b..e2c4f6f9d 100644 --- a/cpctelera/src/sprites/colorReplace/M1/cpct_drawSpriteMaskedAlignedColorizeM1_asmbindings.s +++ b/cpctelera/src/sprites/colorReplace/M1/cpct_drawSpriteMaskedAlignedColorizeM1_asmbindings.s @@ -18,7 +18,7 @@ ;;------------------------------------------------------------------------------- .module cpct_sprites -.include "../../../macros/cpct_undocumentedOpcodes.h.s" +.include "macros/cpct_undocumentedOpcodes.h.s" ;; ;; ASM bindings for <cpct_drawSpriteMaskedAlignedColorizeM1> diff --git a/cpctelera/src/sprites/colorReplace/M1/cpct_drawSpriteMaskedAlignedColorizeM1_cbindings.s b/cpctelera/src/sprites/colorReplace/M1/cpct_drawSpriteMaskedAlignedColorizeM1_cbindings.s index f88de196c..531ee8094 100644 --- a/cpctelera/src/sprites/colorReplace/M1/cpct_drawSpriteMaskedAlignedColorizeM1_cbindings.s +++ b/cpctelera/src/sprites/colorReplace/M1/cpct_drawSpriteMaskedAlignedColorizeM1_cbindings.s @@ -18,7 +18,7 @@ ;;------------------------------------------------------------------------------- .module cpct_sprites -.include "../../../macros/cpct_undocumentedOpcodes.h.s" +.include "macros/cpct_undocumentedOpcodes.h.s" ;; ;; C bindings for <cpct_drawSpriteMaskedAlignedColorizeM1> diff --git a/cpctelera/src/sprites/colorReplace/M1/cpct_drawSpriteMaskedColorizeM1_asmbindings.s b/cpctelera/src/sprites/colorReplace/M1/cpct_drawSpriteMaskedColorizeM1_asmbindings.s index 33d3dd82a..097551a0f 100644 --- a/cpctelera/src/sprites/colorReplace/M1/cpct_drawSpriteMaskedColorizeM1_asmbindings.s +++ b/cpctelera/src/sprites/colorReplace/M1/cpct_drawSpriteMaskedColorizeM1_asmbindings.s @@ -18,7 +18,7 @@ ;;------------------------------------------------------------------------------- .module cpct_sprites -.include "../../../macros/cpct_undocumentedOpcodes.h.s" +.include "macros/cpct_undocumentedOpcodes.h.s" ;; ;; ASM bindings for <cpct_drawSpriteMaskedColorizeM1> diff --git a/cpctelera/src/sprites/colorReplace/M1/cpct_drawSpriteMaskedColorizeM1_cbindings.s b/cpctelera/src/sprites/colorReplace/M1/cpct_drawSpriteMaskedColorizeM1_cbindings.s index abc535c5c..c497bdf07 100644 --- a/cpctelera/src/sprites/colorReplace/M1/cpct_drawSpriteMaskedColorizeM1_cbindings.s +++ b/cpctelera/src/sprites/colorReplace/M1/cpct_drawSpriteMaskedColorizeM1_cbindings.s @@ -18,7 +18,7 @@ ;;------------------------------------------------------------------------------- .module cpct_sprites -.include "../../../macros/cpct_undocumentedOpcodes.h.s" +.include "macros/cpct_undocumentedOpcodes.h.s" ;; ;; C bindings for <cpct_drawSpriteMaskedColorizeM1> diff --git a/cpctelera/src/sprites/colorReplace/M1/cpct_spriteColorizeM1_asmbindings.s b/cpctelera/src/sprites/colorReplace/M1/cpct_spriteColorizeM1_asmbindings.s index b4902424a..067488591 100644 --- a/cpctelera/src/sprites/colorReplace/M1/cpct_spriteColorizeM1_asmbindings.s +++ b/cpctelera/src/sprites/colorReplace/M1/cpct_spriteColorizeM1_asmbindings.s @@ -18,7 +18,7 @@ ;;------------------------------------------------------------------------------- .module cpct_sprites -.include "../../../macros/cpct_undocumentedOpcodes.h.s" +.include "macros/cpct_undocumentedOpcodes.h.s" ;; ;; ASM bindings for <cpct_spriteColorizeM1> diff --git a/cpctelera/src/sprites/colorReplace/M1/cpct_spriteColorizeM1_cbindings.s b/cpctelera/src/sprites/colorReplace/M1/cpct_spriteColorizeM1_cbindings.s index 911a3fd0c..2b2e810b7 100644 --- a/cpctelera/src/sprites/colorReplace/M1/cpct_spriteColorizeM1_cbindings.s +++ b/cpctelera/src/sprites/colorReplace/M1/cpct_spriteColorizeM1_cbindings.s @@ -18,7 +18,7 @@ ;;------------------------------------------------------------------------------- .module cpct_sprites -.include "../../../macros/cpct_undocumentedOpcodes.h.s" +.include "macros/cpct_undocumentedOpcodes.h.s" ;; ;; C bindings for <cpct_spriteColorizeM1> diff --git a/cpctelera/src/sprites/colorReplace/M1/cpct_spriteMaskedColorizeM1_asmbindings.s b/cpctelera/src/sprites/colorReplace/M1/cpct_spriteMaskedColorizeM1_asmbindings.s index 337270684..c9884cea5 100644 --- a/cpctelera/src/sprites/colorReplace/M1/cpct_spriteMaskedColorizeM1_asmbindings.s +++ b/cpctelera/src/sprites/colorReplace/M1/cpct_spriteMaskedColorizeM1_asmbindings.s @@ -18,7 +18,7 @@ ;;------------------------------------------------------------------------------- .module cpct_sprites -.include "../../../macros/cpct_undocumentedOpcodes.h.s" +.include "macros/cpct_undocumentedOpcodes.h.s" ;; ;; ASM bindings for <cpct_spriteMaskedColorizeM1> diff --git a/cpctelera/src/sprites/colorReplace/M1/cpct_spriteMaskedColorizeM1_cbindings.s b/cpctelera/src/sprites/colorReplace/M1/cpct_spriteMaskedColorizeM1_cbindings.s index 871930f81..c47007c43 100644 --- a/cpctelera/src/sprites/colorReplace/M1/cpct_spriteMaskedColorizeM1_cbindings.s +++ b/cpctelera/src/sprites/colorReplace/M1/cpct_spriteMaskedColorizeM1_cbindings.s @@ -18,7 +18,7 @@ ;;------------------------------------------------------------------------------- .module cpct_sprites -.include "../../../macros/cpct_undocumentedOpcodes.h.s" +.include "macros/cpct_undocumentedOpcodes.h.s" ;; ;; C bindings for <cpct_spriteMaskedColorizeM1> From 04a34248f2969c862be31b1ed0941bf7a2d430a7 Mon Sep 17 00:00:00 2001 From: Arnaud <arnaud_bouche@hotmail.com> Date: Fri, 26 Jan 2018 22:41:37 +0100 Subject: [PATCH 22/31] Add new function cpct_setReplaceColors and update others --- .../M0/cpct_drawSpriteColorizeM0.asm | 41 +- .../cpct_drawSpriteColorizeM0_asmbindings.s | 7 +- .../M0/cpct_drawSpriteColorizeM0_cbindings.s | 15 +- ...cpct_drawSpriteMaskedAlignedColorizeM0.asm | 149 +++-- ...priteMaskedAlignedColorizeM0_asmbindings.s | 7 +- ...wSpriteMaskedAlignedColorizeM0_cbindings.s | 17 +- .../M0/cpct_drawSpriteMaskedColorizeM0.asm | 56 +- ...t_drawSpriteMaskedColorizeM0_asmbindings.s | 3 +- ...pct_drawSpriteMaskedColorizeM0_cbindings.s | 11 +- .../colorReplace/M0/cpct_replaceColor.s | 44 ++ .../M0/cpct_setReplaceColorsM0.asm | 87 +++ .../M0/cpct_setReplaceColorsM0_cbinding.s | 31 ++ .../colorReplace/M0/cpct_spriteColorizeM0.asm | 57 +- .../M0/cpct_spriteColorizeM0_asmbindings.s | 10 +- .../M0/cpct_spriteColorizeM0_cbindings.s | 15 +- .../M0/cpct_spriteMaskedColorizeM0.asm | 48 +- .../cpct_spriteMaskedColorizeM0_asmbindings.s | 5 +- .../cpct_spriteMaskedColorizeM0_cbindings.s | 9 +- .../src/sprites/colorReplace/colorReplace.h | 15 +- examples/medium/colorReplace/src/drawing.c | 521 +++++++++--------- 20 files changed, 606 insertions(+), 542 deletions(-) create mode 100644 cpctelera/src/sprites/colorReplace/M0/cpct_replaceColor.s create mode 100644 cpctelera/src/sprites/colorReplace/M0/cpct_setReplaceColorsM0.asm create mode 100644 cpctelera/src/sprites/colorReplace/M0/cpct_setReplaceColorsM0_cbinding.s diff --git a/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteColorizeM0.asm b/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteColorizeM0.asm index a40ef9e87..9ee49f27e 100644 --- a/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteColorizeM0.asm +++ b/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteColorizeM0.asm @@ -25,15 +25,13 @@ ;; Directly replace a color and draw a sprite to video memory. ;; ;; C Definition: -;; void <cpct_drawSpriteColorizeM0> (void* *sprite*, void* *memory*, <u8> *width*, <u8> *height*, <u8> *oldColor*, <u8> *newColor*) __z88dk_callee; +;; void <cpct_drawSpriteColorizeM0> (void* *sprite*, void* *memory*, <u8> *width*, <u8> *height*) __z88dk_callee; ;; ;; Input Parameters (8 bytes): ;; (2B HL') sprite - Source Sprite Pointer (array of pixel data) ;; (2B DE') memory - Destination video memory pointer ;; (1B C' ) height - Sprite Height in bytes (>0) ;; (1B B' ) width - Sprite Width in *bytes* (Beware, *not* in pixels!) -;; (1B L ) oldColor - Color to replace -;; (1B H ) newColor - New color ;; ;; Assembly call (Input parameters on registers): ;; > call cpct_drawSpriteColorizeM0_asm @@ -54,8 +52,6 @@ ;; There is no practical upper limit to this value. Height of a sprite in ;; bytes and pixels is the same value, as bytes only group consecutive pixels in ;; the horizontal space. -;; * *oldColor* must be the index of color (0 to 15) to replace -;; * *newColor* must be the index of the new color (0 to 15) ;; ;; Known limitations: ;; * This function does not do any kind of boundary check or clipping. If you @@ -76,8 +72,8 @@ ;; AF, BC, DE, HL, BC', DE', HL', IX ;; ;; Required memory: -;; C-bindings - 118 bytes -;; ASM-bindings - 108 bytes +;; C-bindings - 165 bytes +;; ASM-bindings - 160 bytes ;; ;; Time Measures: ;; (start code) @@ -100,32 +96,15 @@ ;; Thanks to all of them for their help and support. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -.globl dc_mode0_ct +.globl _cpct_color_old +.globl _cpct_color_new -;; Macro to convert Pixel to xAxC xBxD format -.macro convertPixel - ;; From cpct_px2byteM0 - ld bc, #dc_mode0_ct ;; [3] BC points to conversion table (dc_mode0_ct) - - ;; Compute BC += A - add c ;; [1] | C += A - ld c, a ;; [1] | - sub a ;; [1] A = 0 (preserving Carry Flag) - adc b ;; [1] | B += Carry - ld b, a ;; [1] | - - ;; A = *(BC + A) - ld a, (bc) ;; [2] A = Value stored at the table pointed by BC -.endm - - ;; Convert newColor to pixel format (E) - ld a, h ;; [1] A = H new color index - convertPixel ;; [10] | Convert into A + ;; newColor to pixel format (E) + ld a, (_cpct_color_new);; [4] A = mem new color index ld e, a ;; [1] | E = A new color : xAxC xBxD - ;; Convert oldColor to pixel format (D) - ld a, l ;; [1] A = L old color index - convertPixel ;; [10] | Convert into A + ;; oldColor to pixel format (D) + ld a, (_cpct_color_old);; [4] A = mem old color index ld d, a ;; [1] | D = A old color : xAxC xBxD ld c, #0x55 ;; [2] C = Mask to get pixel A : xAxC xBxD @@ -147,7 +126,7 @@ lineLoop: and c ;; [2] A |= C (C = 0x55) : xBxB xBxB cp d ;; [1] Test if pixel (A) is the old colour to be replaced (D) - jr nz, readPixelA ;; [2/3] If not equal go to next pixel + jr nz, readPixelA ;; [2/3] If not equal go to next pixel ld a, e ;; [1] else A = new colour to set (E) ;; Pixel Mode 0 = ABAB ABAB diff --git a/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteColorizeM0_asmbindings.s b/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteColorizeM0_asmbindings.s index 073609b70..01bfcad7c 100644 --- a/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteColorizeM0_asmbindings.s +++ b/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteColorizeM0_asmbindings.s @@ -1,7 +1,7 @@ ;;-----------------------------LICENSE NOTICE------------------------------------ ;; This file is part of CPCtelera: An Amstrad CPC Game Engine -;; Copyright (C) 2017 Arnaud Bouche (@Arnaud6128) -;; Copyright (C) 2017 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) +;; Copyright (C) 2018 Arnaud Bouche (@Arnaud6128) +;; Copyright (C) 2018 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) ;; ;; This program is free software: you can redistribute it and/or modify ;; it under the terms of the GNU Lesser General Public License as published by @@ -18,7 +18,7 @@ ;;------------------------------------------------------------------------------- .module cpct_sprites -.include "../../../macros/cpct_undocumentedOpcodes.h.s" +.include "../macros/cpct_undocumentedOpcodes.s" ;; ;; ASM bindings for <cpct_drawSpriteColorizeM0> @@ -27,7 +27,6 @@ cpct_drawSpriteColorizeM0_asm:: ;; Assembly entry point ;; GET Parameters from the stack ld (dms_restore_ix + 2), ix ;; [6] Save IX to restore it before returning - pop hl ;; [3] HL = Return Address ;;.include /cpct_drawSpriteColorizeM0.asm/ diff --git a/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteColorizeM0_cbindings.s b/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteColorizeM0_cbindings.s index f4ad4b2f5..9b8ed88e2 100644 --- a/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteColorizeM0_cbindings.s +++ b/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteColorizeM0_cbindings.s @@ -1,7 +1,7 @@ ;;-----------------------------LICENSE NOTICE------------------------------------ ;; This file is part of CPCtelera: An Amstrad CPC Game Engine -;; Copyright (C) 2017 Arnaud Bouche (@Arnaud6128) -;; Copyright (C) 2017 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) +;; Copyright (C) 2018 Arnaud Bouche (@Arnaud6128) +;; Copyright (C) 2018 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) ;; ;; This program is free software: you can redistribute it and/or modify ;; it under the terms of the GNU Lesser General Public License as published by @@ -18,18 +18,18 @@ ;;------------------------------------------------------------------------------- .module cpct_sprites -.include "../../../macros/cpct_undocumentedOpcodes.h.s" +.include "../macros/cpct_undocumentedOpcodes.s" ;; ;; C bindings for <cpct_drawSpriteColorizeM0> ;; -;; 33 us, 10 bytes +;; 33 us, 8 bytes ;; _cpct_drawSpriteColorizeM0:: ;; GET Parameters from the stack ld (dms_restore_ix + 2), ix ;; [6] Save IX to restore it before returning - pop hl ;; [3] HL = Return Address + pop de ;; [3] DE = Return Address exx pop hl ;; [3] HL' = Source address (Sprite) @@ -37,9 +37,8 @@ _cpct_drawSpriteColorizeM0:: pop bc ;; [5] BC' = (B = Sprite Height, C = Width) exx - ex (sp), hl ;; [6] HL = (H = newColor, L = oldColor) - ;; ... and leave Return Address at (SP) as we don't need to restore - ;; ... stack status because callin convention is __z88dk_callee + push de ;; [4] Put returning address in the stack again + ;; as this function uses __z88dk_callee convention .include /cpct_drawSpriteColorizeM0.asm/ diff --git a/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteMaskedAlignedColorizeM0.asm b/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteMaskedAlignedColorizeM0.asm index 981c21ab2..a0dda77a4 100644 --- a/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteMaskedAlignedColorizeM0.asm +++ b/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteMaskedAlignedColorizeM0.asm @@ -18,8 +18,6 @@ ;;------------------------------------------------------------------------------- .module cpct_sprites -.globl dc_mode0_ct - ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; Function: cpct_drawSpriteMaskedAlignedColorizeM0 @@ -28,15 +26,13 @@ ;; ;; C Definition: ;; void <cpct_drawSpriteMaskedAlignedColorizeM0> (void* *sprite*, void* *memory*, <u8> *width*, <u8> *height*, -;; <u8> *oldColor*, <u8> *newColor*, <u8*> *pmasktable*) __z88dk_callee; +;; <u8*> *pmasktable*) __z88dk_callee; ;; -;; Input Parameters (10 bytes): +;; Input Parameters (8 bytes): ;; (2B HL') sprite - Source Sprite Pointer (array of pixel data) ;; (2B DE') memory - Destination video memory pointer ;; (1B C' ) height - Sprite Height in bytes (>0) ;; (1B B' ) width - Sprite Width in *bytes* (Beware, *not* in pixels!) -;; (1B E ) oldColor - Color to replace -;; (1B D ) newColor - New color ;; (2B HL) pmasktable - Pointer to the aligned mask table used to create transparency ;; ;; Assembly call (Input parameters on registers): @@ -58,8 +54,6 @@ ;; There is no practical upper limit to this value. Height of a sprite in ;; bytes and pixels is the same value, as bytes only group consecutive pixels in ;; the horizontal space. -;; * *oldColor* must be the index of color (0 to 15) to replace -;; * *newColor* must be the index of the new color (0 to 15) ;; ;; Known limitations: ;; * This function does not do any kind of boundary check or clipping. If you @@ -80,8 +74,8 @@ ;; AF, BC, DE, HL, BC', DE', HL', IX ;; ;; Required memory: -;; C-bindings - 112 bytes -;; ASM-bindings - 96 bytes +;; C-bindings - 165 bytes +;; ASM-bindings - 160 bytes ;; ;; Time Measures: ;; (start code) @@ -104,97 +98,82 @@ ;; Thanks to all of them for their help and support. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; Macro to convert Pixel to xAxC xBxD format -.macro convertPixel - ;; From cpct_px2byteM0 - ld bc, #dc_mode0_ct ;; [3] BC points to conversion table (dc_mode0_ct) - - ;; Compute BC += A - add c ;; [1] | C += A - ld c, a ;; [1] | - sub a ;; [1] A = 0 (preserving Carry Flag) - adc b ;; [1] | B += Carry - ld b, a ;; [1] | - - ;; A = *(BC + A) - ld a, (bc) ;; [2] A = Value stored at the table pointed by BC -.endm +.globl _cpct_color_old +.globl _cpct_color_new - ;; Convert newColor to pixel format (E) - ld a, h ;; [1] A = H new color index - convertPixel ;; [10] | Convert into A + ;; newColor to pixel format (E) + ld a, (_cpct_color_new);; [4] A = mem new color index ld e, a ;; [1] | E = A new color : xAxC xBxD - ;; Convert oldColor to pixel format (D) - ld a, l ;; [1] A = L old color index - convertPixel ;; [10] | Convert into A - ld b, d - ld d, a ;; [1] | D = A old color : xAxC xBxD - - ld c, #0x55 ;; [2] C = Mask to get pixel A : xAxC xBxD - exx ;; [1] Switch to Alternate registers - - ld__ixl_c ;; [1] IXL = C (Width) - ld c, b ;; [1] C = B (Height) - -convertLoop: - push de ;; [4] Store DE start line (DestMem) - ld__b_ixl ;; [2] B = IXL (Sprite Width) + ;; oldColor to pixel format (D) + ld a, (_cpct_color_old);; [4] A = mem old color index + ld b, d ;; [1] B = D (Masked table adress High Byte) + ld d, a ;; [1] | D = A old color : xAxC xBxD + + ld c, #0x55 ;; [2] C = Mask to get pixel A : xAxC xBxD + exx ;; [1] Switch to Alternate registers + + ld__ixl_c ;; [1] IXL = C (Width) + ld c, b ;; [1] C = B (Height) + +convertLoop: + push de ;; [4] Store DE start line (DestMem) + ld__b_ixl ;; [2] B = IXL (Sprite Width) lineLoop: - ld a, (hl) ;; [2] A = (HL) current Byte of sprite + ld a, (hl) ;; [2] A = (HL) current Byte of sprite exx ;; [1] Switch to Default registers - - ld l, a ;; [1] L = A current Byte of sprite : ABAB ABAB - and c ;; [2] A |= C (C = 0x55) : xBxB xBxB - - cp d ;; [1] Test if pixel (A) is the old colour to be replaced (D) - jr nz, readPixelA ;; [2/3] If not equal go to next pixel + + ld l, a ;; [1] L = A current Byte of sprite : ABAB ABAB + and c ;; [2] A |= C (C = 0x55) : xBxB xBxB + + cp d ;; [1] Test if pixel (A) is the old colour to be replaced (D) + jr nz, readPixelA ;; [2/3] If not equal go to next pixel ld a, e ;; [1] else A = new colour to set (E) ;; Pixel Mode 0 = ABAB ABAB readPixelA: - ld h, a ;; [1] H = A (current colorized sprite) : xBxB xBxB - ld a, l ;; [1] L = A current Byte of sprite : ABAB ABAB - rrca ;; [1] A (current byte of sprite) >> 1 : ABAB ABAB -> xABA BABA - and c ;; [2] A |= Mask (0x55) : xAxA xAxA - - cp d ;; [1] Test if pixel (A) is the old colour to be replaced (D) - jr nz, readPixelB ;; [2/3] If not equal go to next pixel + ld h, a ;; [1] H = A (current colorized sprite) : xBxB xBxB + ld a, l ;; [1] L = A current Byte of sprite : ABAB ABAB + rrca ;; [1] A (current byte of sprite) >> 1 : ABAB ABAB -> xABA BABA + and c ;; [2] A |= Mask (0x55) : xAxA xAxA + + cp d ;; [1] Test if pixel (A) is the old colour to be replaced (D) + jr nz, readPixelB ;; [2/3] If not equal go to next pixel ld a, e ;; [1] else A = new colour to set (E) - + readPixelB: - rlca ;; [1] A = xAxA xAxA << 1 : AxAx AxAx - or h ;; [1] A |= H (xBxB xBxB) : ABAB ABAB + rlca ;; [1] A = xAxA xAxA << 1 : AxAx AxAx + or h ;; [1] A |= H (xBxB xBxB) : ABAB ABAB drawByte: ld h, b ;; [1] H = B (Masked table adress High Byte) - ld l, a ;; [1] Access mask table element (table must be 256-byte aligned) - exx ;; [1] Switch to Alternate registers - - ld a, (de) ;; [2] Get the value of the byte of the screen where we are going to draw - exx ;; [1] Switch to Default registers - - and (hl) ;; [2] Erase background part that is to be overwritten (Mask step 1) - or l ;; [1] Add up background and sprite information in one byte (Mask step 2) - exx ;; [1] Switch to Alternate registers - - ld (de), a ;; [2] Save modified background + sprite data information into memory + ld l, a ;; [1] Access mask table element (table must be 256-byte aligned) + exx ;; [1] Switch to Alternate registers + + ld a, (de) ;; [2] Get the value of the byte of the screen where we are going to draw + exx ;; [1] Switch to Default registers + + and (hl) ;; [2] Erase background part that is to be overwritten (Mask step 1) + or l ;; [1] Add up background and sprite information in one byte (Mask step 2) + exx ;; [1] Switch to Alternate registers + + ld (de), a ;; [2] Save modified background + sprite data information into memory - inc hl ;; [2] Next byte sprite source - inc de ;; [2] Next byte sprite colorized - djnz lineLoop ;; [3] Decrement B (Width) if B != 0 goto lineLoop - - dec c ;; [1] Decrement C (Height) - jr z, end ;; [2/3] If C == O goto end + inc hl ;; [2] Next byte sprite source + inc de ;; [2] Next byte sprite colorized + djnz lineLoop ;; [3] Decrement B (Width) if B != 0 goto lineLoop + + dec c ;; [1] Decrement C (Height) + jr z, end ;; [2/3] If C == O goto end - pop de ;; [3] Restore DE start line (DestMem) + pop de ;; [3] Restore DE start line (DestMem) ld a, d ;; [1] Start of next pixel line normally is 0x0800 bytes away. add #0x08 ;; [2] so we add it to DE (just by adding 0x08 to D) ld d, a ;; [1] - and #0x38 ;; [2] We check if we have crossed memory boundary (every 8 pixel lines).. - + and #0x38 ;; [2] We check if we have crossed memory boundary (every 8 pixel lines).. + jr nz, convertLoop ;; [2/3] .. by checking the 4 bits that identify present memory line. ;; .... If 0, we have crossed boundaries @@ -205,11 +184,11 @@ dms_sprite_8bit_boundary_crossed: ld a, d ;; [1] -- which effectively is the same as moving it 1 bank backwards and then adc #0xC0 ;; [2] -- 50 bytes forwards (which is what we want to move it to the next pixel line) ld d, a ;; [1] -- Calculations are made with 8 bit maths as it is faster than other alternatives here - - jr convertLoop ;; [3] Jump to continue with next pixel line + + jr convertLoop ;; [3] Jump to continue with next pixel line end: pop de ;; [3] Empty stack by getting last element (DestMem) - ;; Return is included in bindings - - + ;; Return is included in bindings + + diff --git a/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteMaskedAlignedColorizeM0_asmbindings.s b/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteMaskedAlignedColorizeM0_asmbindings.s index f566e8fc5..868def72a 100644 --- a/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteMaskedAlignedColorizeM0_asmbindings.s +++ b/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteMaskedAlignedColorizeM0_asmbindings.s @@ -1,7 +1,7 @@ ;;-----------------------------LICENSE NOTICE------------------------------------ ;; This file is part of CPCtelera: An Amstrad CPC Game Engine -;; Copyright (C) 2017 Arnaud Bouche (@Arnaud6128) -;; Copyright (C) 2017 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) +;; Copyright (C) 2018 Arnaud Bouche (@Arnaud6128) +;; Copyright (C) 2018 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) ;; ;; This program is free software: you can redistribute it and/or modify ;; it under the terms of the GNU Lesser General Public License as published by @@ -18,7 +18,7 @@ ;;------------------------------------------------------------------------------- .module cpct_sprites -.include "../../../macros/cpct_undocumentedOpcodes.h.s" +.include "../macros/cpct_undocumentedOpcodes.s" ;; ;; ASM bindings for <cpct_drawSpriteMaskedAlignedColorizeM0> @@ -27,7 +27,6 @@ cpct_drawSpriteMaskedAlignedColorizeM0_asm:: ;; Assembly entry point ;; GET Parameters from the stack ld (dms_restore_ix + 2), ix ;; [6] Save IX to restore it before returning - pop hl ;; [3] HL = Return Address .include /cpct_drawSpriteMaskedAlignedColorizeM0.asm/ diff --git a/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteMaskedAlignedColorizeM0_cbindings.s b/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteMaskedAlignedColorizeM0_cbindings.s index f8953c60b..01d9eee57 100644 --- a/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteMaskedAlignedColorizeM0_cbindings.s +++ b/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteMaskedAlignedColorizeM0_cbindings.s @@ -1,7 +1,7 @@ ;;-----------------------------LICENSE NOTICE------------------------------------ ;; This file is part of CPCtelera: An Amstrad CPC Game Engine -;; Copyright (C) 2017 Arnaud Bouche (Arnaud6128) -;; Copyright (C) 2017 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) +;; Copyright (C) 2018 Arnaud Bouche (@Arnaud6128) +;; Copyright (C) 2018 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) ;; ;; This program is free software: you can redistribute it and/or modify ;; it under the terms of the GNU Lesser General Public License as published by @@ -18,12 +18,12 @@ ;;------------------------------------------------------------------------------- .module cpct_sprites -.include "../../../macros/cpct_undocumentedOpcodes.h.s" +.include "../macros/cpct_undocumentedOpcodes.s" ;; ;; C bindings for <cpct_drawSpriteMaskedAlignedColorizeM0> ;; -;; 39 us, 16 bytes +;; 39 us, 8 bytes ;; _cpct_drawSpriteMaskedAlignedColorizeM0:: @@ -37,13 +37,10 @@ _cpct_drawSpriteMaskedAlignedColorizeM0:: pop bc ;; [5] BC' = (B = Sprite Height, C = Width) exx ;; [1] Switch to Default registers - pop de ;; [3] DE = (D = newColor, E = oldColor) + pop de ;; [3] DE = Table Mask address - ex (sp), hl ;; [6] HL = Table Mask address - ;; ... and leave Return Address at (SP) as we don't need to restore - ;; ... stack status because callin convention is __z88dk_callee - - ex de, hl ;; [1] HL <-> DE + push hl ;; [4] Put returning address in the stack again + ;; as this function uses __z88dk_callee convention .include /cpct_drawSpriteMaskedAlignedColorizeM0.asm/ diff --git a/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteMaskedColorizeM0.asm b/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteMaskedColorizeM0.asm index 8f63f4c99..7862cdaeb 100644 --- a/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteMaskedColorizeM0.asm +++ b/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteMaskedColorizeM0.asm @@ -1,7 +1,7 @@ ;;-----------------------------LICENSE NOTICE------------------------------------ ;; This file is part of CPCtelera: An Amstrad CPC Game Engine -;; Copyright (C) 2017 Arnaud Bouche -;; Copyright (C) 2017 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) +;; Copyright (C) 2018 Arnaud Bouche (@Arnaud6128) +;; Copyright (C) 2018 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) ;; ;; This program is free software: you can redistribute it and/or modify ;; it under the terms of the GNU Lesser General Public License as published by @@ -18,8 +18,6 @@ ;;------------------------------------------------------------------------------- .module cpct_sprites -.globl dc_mode0_ct - ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; Function: cpct_drawSpriteMaskedColorizeM0 @@ -27,15 +25,13 @@ ;; Directly replace a color and draw a sprite Masked to video memory. ;; ;; C Definition: -;; void <cpct_drawSpriteMaskedColorizeM0> (void* *sprite*, void* *memory*, <u8> *width*, <u8> *height*, <u8> *oldColor*, <u8> *newColor*) __z88dk_callee; +;; void <cpct_drawSpriteMaskedColorizeM0> (void* *sprite*, void* *memory*, <u8> *width*, <u8> *height*) __z88dk_callee; ;; -;; Input Parameters (8 bytes): +;; Input Parameters (6 bytes): ;; (2B HL') sprite - Source Sprite Pointer (array of pixel data) ;; (2B DE') memory - Destination video memory pointer ;; (1B C' ) height - Sprite Height in bytes (>0) ;; (1B B' ) width - Sprite Width in *bytes* (Beware, *not* in pixels!) -;; (1B L ) oldColor - Color to replace -;; (1B H ) newColor - New color ;; ;; Assembly call (Input parameters on registers): ;; > call cpct_drawSpriteMaskedColorizeM0_asm @@ -61,8 +57,6 @@ ;; There is no practical upper limit to this value. Height of a sprite in ;; bytes and pixels is the same value, as bytes only group consecutive pixels in ;; the horizontal space. -;; * *oldColor* must be the index of color (0 to 15) to replace -;; * *newColor* must be the index of the new color (0 to 15) ;; ;; Known limitations: ;; * This function does not do any kind of boundary check or clipping. If you @@ -80,20 +74,21 @@ ;; * This function requires the CPC firmware to be DISABLED. Otherwise, random crashes might happen due to side effects. ;; ;; Destroyed Register values: -;; AF, BC, DE, HL, BC', DE', HL', IX +;; AF, BC, DE, BC', DE', HL', IX ;; ;; Required memory: -;; C-bindings - 115 bytes -;; ASM-bindings - 102 bytes +;; C-bindings - 165 bytes +;; ASM-bindings - 160 bytes ;; ;; Time Measures: ;; (start code) ;; Case | microSecs (us) | CPU Cycles ;; ---------------------------------------------------------------- -;; Best | 29 + (50 + 36W)H | 116 + (200 + 144W)H +;; Best | | +;; Worst | | ;; ---------------------------------------------------------------- -;; W=2,H=16 | 1981 | 7924 -;; W=4,H=32 | 6237 | 24948 +;; W=2,H=16 | | +;; W=4,H=32 | | ;; ---------------------------------------------------------------- ;; Asm saving | -16 | -64 ;; ---------------------------------------------------------------- @@ -107,34 +102,21 @@ ;; Thanks to all of them for their help and support. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; Macro to convert Pixel to xAxC xBxD format -.macro convertPixel - ;; From cpct_px2byteM0 - ld bc, #dc_mode0_ct ;; [3] BC points to conversion table (dc_mode0_ct) - - ;; Compute BC += A - add c ;; [1] | C += A - ld c, a ;; [1] | - sub a ;; [1] A = 0 (preserving Carry Flag) - adc b ;; [1] | B += Carry - ld b, a ;; [1] | - - ;; A = *(BC + A) - ld a, (bc) ;; [2] A = Value stored at the table pointed by BC -.endm +.globl _cpct_color_old +.globl _cpct_color_new - ;; Convert newColor to pixel format (E) - ld a, h ;; [1] A = H new color index - convertPixel ;; [10] | Convert into A + ;; newColor to pixel format (E) + ld a, (_cpct_color_new);; [4] A = mem new color index ld e, a ;; [1] | E = A new color : xAxC xBxD - ;; Convert oldColor to pixel format (D) - ld a, l ;; [1] A = L old color index - convertPixel ;; [10] | Convert into A + ;; oldColor to pixel format (D) + ld a, (_cpct_color_old);; [4] A = mem old color index ld d, a ;; [1] | D = A old color : xAxC xBxD ld c, #0x55 ;; [2] C = Mask to get pixel A : xAxC xBxD + ld c, #0x55 ;; [2] C = Mask to get pixel A : xAxC xBxD + exx ;; [1] Switch to Alternate registers ld__ixl_c ;; [1] IXL = C (Width) diff --git a/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteMaskedColorizeM0_asmbindings.s b/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteMaskedColorizeM0_asmbindings.s index 48bc1ef3c..a8806e008 100644 --- a/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteMaskedColorizeM0_asmbindings.s +++ b/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteMaskedColorizeM0_asmbindings.s @@ -18,7 +18,7 @@ ;;------------------------------------------------------------------------------- .module cpct_sprites -.include "../../../macros/cpct_undocumentedOpcodes.h.s" +.include "../macros/cpct_undocumentedOpcodes.s" ;; ;; ASM bindings for <cpct_drawSpriteMaskedColorizeM0> @@ -27,7 +27,6 @@ cpct_drawSpriteMaskedColorizeM0_asm:: ;; Assembly entry point ;; GET Parameters from the stack ld (dms_restore_ix + 2), ix ;; [6] Save IX to restore it before returning - pop hl ;; [3] HL = Return Address .include /cpct_drawSpriteMaskedColorizeM0.asm/ diff --git a/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteMaskedColorizeM0_cbindings.s b/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteMaskedColorizeM0_cbindings.s index 18f336eb5..1f0fd6e66 100644 --- a/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteMaskedColorizeM0_cbindings.s +++ b/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteMaskedColorizeM0_cbindings.s @@ -18,18 +18,18 @@ ;;------------------------------------------------------------------------------- .module cpct_sprites -.include "../../../macros/cpct_undocumentedOpcodes.h.s" +.include "../macros/cpct_undocumentedOpcodes.s" ;; ;; C bindings for <cpct_drawSpriteMaskedColorizeM0> ;; -;; 33 us, 13 bytes +;; 33 us, 8 bytes ;; _cpct_drawSpriteMaskedColorizeM0:: ;; GET Parameters from the stack ld (dms_restore_ix + 2), ix ;; [6] Save IX to restore it before returning - pop hl ;; [3] HL = Return Address + pop de ;; [3] DE = Return Address exx pop hl ;; [3] HL' = Source address (Sprite) @@ -37,9 +37,8 @@ _cpct_drawSpriteMaskedColorizeM0:: pop bc ;; [5] BC' = (B = Sprite Height, C = Width) exx - ex (sp), hl ;; [6] HL = (H = newColor, L = oldColor) - ;; ... and leave Return Address at (SP) as we don't need to restore - ;; ... stack status because callin convention is __z88dk_callee + push de ;; [4] Put returning address in the stack again + ;; as this function uses __z88dk_callee convention .include /cpct_drawSpriteMaskedColorizeM0.asm/ diff --git a/cpctelera/src/sprites/colorReplace/M0/cpct_replaceColor.s b/cpctelera/src/sprites/colorReplace/M0/cpct_replaceColor.s new file mode 100644 index 000000000..260c2ea15 --- /dev/null +++ b/cpctelera/src/sprites/colorReplace/M0/cpct_replaceColor.s @@ -0,0 +1,44 @@ +;;-----------------------------LICENSE NOTICE------------------------------------ +;; This file is part of CPCtelera: An Amstrad CPC Game Engine +;; Copyright (C) 2018 Arnaud Bouche (@Arnaud6128) +;; Copyright (C) 2018 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) +;; +;; This program is free software: you can redistribute it and/or modify +;; it under the terms of the GNU Lesser General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU Lesser General Public License for more details. +;; +;; You should have received a copy of the GNU Lesser General Public License +;; along with this program. If not, see <http://www.gnu.org/licenses/>. +;;------------------------------------------------------------------------------- +.module cpct_sprites + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; +;; Variables: cpct_color_old, cpct_color_new +;; +;; Contains the colors to be used by theses functions: +;; * cpct_setReplaceColors +;; * cpct_spriteColorizeM0 +;; * cpct_spriteColorizeM1 +;; * cpct_drawSpriteColorizeM0 +;; * cpct_drawSpriteColorizeM1 +;; +;; C Definition: +;; <u8> <cpct_color_old>; +;; <u8> <cpct_color_new>; +;; +;; Known limitations: +;; * These color are used for Mode0 (0 to 15) and Mode1 (0 to 3) +;; * You may assing a value to this seed direcly from C or ASM. If directly accessed +;; from ASM, do not forget to put an underscore in front (_cpct_color_old and _cpct_color_new). +;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +_cpct_color_old:: .db #00 +_cpct_color_new:: .db #00 \ No newline at end of file diff --git a/cpctelera/src/sprites/colorReplace/M0/cpct_setReplaceColorsM0.asm b/cpctelera/src/sprites/colorReplace/M0/cpct_setReplaceColorsM0.asm new file mode 100644 index 000000000..47c9308a7 --- /dev/null +++ b/cpctelera/src/sprites/colorReplace/M0/cpct_setReplaceColorsM0.asm @@ -0,0 +1,87 @@ +;;-----------------------------LICENSE NOTICE------------------------------------ +;; This file is part of CPCtelera: An Amstrad CPC Game Engine +;; Copyright (C) 2018 Arnaud Bouche (@Arnaud6128) +;; Copyright (C) 2018 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) +;; +;; This program is free software: you can redistribute it and/or modify +;; it under the terms of the GNU Lesser General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU Lesser General Public License for more details. +;; +;; You should have received a copy of the GNU Lesser General Public License +;; along with this program. If not, see <http://www.gnu.org/licenses/>. +;;------------------------------------------------------------------------------- +.module cpct_sprites + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; +;; Function: cpct_setReplaceColorsM0 +;; +;; Sets the colors to be used with the replace colors for Mode 0 functions +;; +;; C Definition: +;; void <cpct_setReplaceColorsM0> (<u8> *oldColor*, <u8> *newColor*) __z88dk_fastcall; +;; +;; Input Parameters (2 bytes): +;; (1B D) *oldColor* - Color to be replaced. +;; (1B E) *newColor* - Color to set. +;; +;; Assembly call: +;; > call cpct_setReplaceColorsM0 +;; +;; Parameter Restrictions: +;; * There is not check on the color value according to the Mode 0 (0 to 15) +;; +;; Destroyed Register values: +;; A, BC, DE +;; +;; Required memory: +;; 8 bytes +;; +;; Time Measures: +;; (start code) +;; Case | microSecs (us) | CPU Cycles +;; ----------------------------------------- +;; Any | 14 | 56 +;; ----------------------------------------- +;; (end code) +;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +.globl dc_mode0_ct + +;; Macro to convert Pixel to xAxC xBxD format +.macro convertPixel + ;; From cpct_px2byteM0 + ld bc, #dc_mode0_ct ;; [3] BC points to conversion table (dc_mode0_ct) + + ;; Compute BC += A + add c ;; [1] | C += A + ld c, a ;; [1] | + sub a ;; [1] A = 0 (preserving Carry Flag) + adc b ;; [1] | B += Carry + ld b, a ;; [1] | + + ;; A = *(BC + A) + ld a, (bc) ;; [2] A = Value stored at the table pointed by BC +.endm + +.globl _cpct_color_old +.globl _cpct_color_new + + ;; Convert New color + ld a, h ;; [1] A = H new color + convertPixel ;; [10] | Convert into A + ld (_cpct_color_new), a ;; [3] | store color in memory + + ;; Convert Old color + ld a, l ;; [1] A = L old color + convertPixel ;; [10] | Convert into A + ld (_cpct_color_old), a ;; [3] | store color in memory + + ret ;; [3] \ No newline at end of file diff --git a/cpctelera/src/sprites/colorReplace/M0/cpct_setReplaceColorsM0_cbinding.s b/cpctelera/src/sprites/colorReplace/M0/cpct_setReplaceColorsM0_cbinding.s new file mode 100644 index 000000000..5792fed64 --- /dev/null +++ b/cpctelera/src/sprites/colorReplace/M0/cpct_setReplaceColorsM0_cbinding.s @@ -0,0 +1,31 @@ +;;-----------------------------LICENSE NOTICE------------------------------------ +;; This file is part of CPCtelera: An Amstrad CPC Game Engine +;; Copyright (C) 2018 Arnaud Bouche (@Arnaud6128) +;; Copyright (C) 2018 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) +;; +;; This program is free software: you can redistribute it and/or modify +;; it under the terms of the GNU Lesser General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU Lesser General Public License for more details. +;; +;; You should have received a copy of the GNU Lesser General Public License +;; along with this program. If not, see <http://www.gnu.org/licenses/>. +;;------------------------------------------------------------------------------- +.module cpct_sprites + +;; +;; C bindings for <cpct_px2byteM0> +;; +;; 9 us, 2 bytes +;; +_cpct_setReplaceColorsM0:: + ;; Recover parameters from the stack + pop hl ;; [3] HL = Return Address + ex (sp), hl ;; [6] HL => L : Old Color, H : New Color + +.include /cpct_setReplaceColorsM0.asm/ \ No newline at end of file diff --git a/cpctelera/src/sprites/colorReplace/M0/cpct_spriteColorizeM0.asm b/cpctelera/src/sprites/colorReplace/M0/cpct_spriteColorizeM0.asm index f319db09c..a6d9090c0 100644 --- a/cpctelera/src/sprites/colorReplace/M0/cpct_spriteColorizeM0.asm +++ b/cpctelera/src/sprites/colorReplace/M0/cpct_spriteColorizeM0.asm @@ -25,15 +25,13 @@ ;; Replace a color in a sprite and copy to another or the same sprite. ;; ;; C Definition: -;; void <cpct_spriteColorizeM0> (void* *sprite*, void* *spriteColor*, <u8> *width*, <u8> *height*, <u8> *oldColor*, <u8> *newColor*) __z88dk_callee; +;; void <cpct_spriteColorizeM0> (void* *sprite*, void* *spriteColor*, <u8> *width*, <u8> *height*) __z88dk_callee; ;; ;; Input Parameters (6 bytes): ;; (2B HL') sprite - Source Sprite Pointer (array of pixel data) ;; (2B DE') spriteColor - Destination Sprite Pointer (can be also the Source Sprite) (array of pixel data) ;; (1B C' ) height - Sprite Height in bytes (>0) ;; (1B B' ) width - Sprite Width in *bytes* (Beware, *not* in pixels!) -;; (1B L ) oldColor - Color to replace -;; (1B H ) newColor - New color ;; ;; Assembly call (Input parameters on registers): ;; > call cpct_spriteColorizeM0_asm @@ -51,33 +49,31 @@ ;; There is no practical upper limit to this value. Height of a sprite in ;; bytes and pixels is the same value, as bytes only group consecutive pixels in ;; the horizontal space. -;; * *oldColor* must be the index of color (0 to 15) to replace -;; * *newColor* must be the index of the new color (0 to 15) ;; ;; Known limitations: ;; * This function *will not work from ROM*, as it uses self-modifying code. ;; * This function requires the CPC firmware to be DISABLED. Otherwise, random crashes might happen due to side effects. ;; ;; Destroyed Register values: -;; AF, BC, DE, HL, BC', DE', HL', IX +;; AF, BC, DE, BC', DE', HL', IX ;; ;; Required memory: -;; C-bindings - 81 bytes -;; ASM-bindings - 67 bytes +;; C-bindings - 165 bytes +;; ASM-bindings - 160 bytes ;; ;; Time Measures: ;; (start code) ;; Case | microSecs (us) | CPU Cycles ;; ---------------------------------------------------------------- -;; | 29 + (6 + 33W)H | 116 + (24 + 132W)H +;; | 29 + (33 + 4W)H | 116 + (132 + 16W)H ;; ---------------------------------------------------------------- -;; W=2,H=16 | 1181 | 4724 -;; W=4,H=32 | 4445 | 17780 +;; W=2,H=16 | 685 | 2740 +;; W=4,H=32 | 1597 | 6388 ;; ---------------------------------------------------------------- ;; Asm saving | -16 | -64 ;; ---------------------------------------------------------------- ;; (end code) -;; W = *width* in bytes, H = *height* in bytes +;; W = *width* in bytes, H = *height* in bytes, HH = [(H-1)/8] ;; ;; Credits: ;; Original routine optimized by @Docent and discussed in CPCWiki : @@ -86,35 +82,19 @@ ;; Thanks to all of them for their help and support. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -.globl dc_mode0_ct +.globl _cpct_color_old +.globl _cpct_color_new -;; Macro to convert Pixel to xAxC xBxD format -.macro convertPixel - ;; From cpct_px2byteM0 - ld bc, #dc_mode0_ct ;; [3] BC points to conversion table (dc_mode0_ct) - - ;; Compute BC += A - add c ;; [1] | C += A - ld c, a ;; [1] | - sub a ;; [1] A = 0 (preserving Carry Flag) - adc b ;; [1] | B += Carry - ld b, a ;; [1] | - - ;; A = *(BC + A) - ld a, (bc) ;; [2] A = Value stored at the table pointed by BC -.endm - - ;; Convert newColor to pixel format (E) - ld a, h ;; [1] A = H new color index - convertPixel ;; [10] | Convert into A + ;; newColor to pixel format (E) + ld a, (_cpct_color_new);; [4] A = mem new color index ld e, a ;; [1] | E = A new color : xAxC xBxD - ;; Convert oldColor to pixel format (D) - ld a, l ;; [1] A = L old color index - convertPixel ;; [10] | Convert into A + ;; oldColor to pixel format (D) + ld a, (_cpct_color_old);; [4] A = mem old color index ld d, a ;; [1] | D = A old color : xAxC xBxD ld c, #0x55 ;; [2] C = Mask to get pixel A : xAxC xBxD + exx ;; [1] Switch to Alternate registers ld__ixl_c ;; [1] IXL = C (Width) @@ -124,7 +104,7 @@ convertLoop: ld__b_ixl ;; [2] B = IXL (Sprite Width) lineLoop: - ld a, (hl) ;; [2] A = (HL) current Byte of sprite + ld a, (hl) ;; [2] A = (HL') current Byte of sprite exx ;; [1] Switch to Default registers ld l, a ;; [1] L = A current Byte of sprite : ABAB ABAB @@ -159,8 +139,7 @@ setByte: nextLine: dec c ;; [1] Decrement C (Height) - jr nz, convertLoop ;; [2/3] If != O goto convertLoop + jr nz, convertLoop ;; [1] If != O goto convertLoop end: - ;; Return is included in bindings - + ;; Return is included in bindings \ No newline at end of file diff --git a/cpctelera/src/sprites/colorReplace/M0/cpct_spriteColorizeM0_asmbindings.s b/cpctelera/src/sprites/colorReplace/M0/cpct_spriteColorizeM0_asmbindings.s index 3339b8ea5..1362dbb6b 100644 --- a/cpctelera/src/sprites/colorReplace/M0/cpct_spriteColorizeM0_asmbindings.s +++ b/cpctelera/src/sprites/colorReplace/M0/cpct_spriteColorizeM0_asmbindings.s @@ -18,19 +18,19 @@ ;;------------------------------------------------------------------------------- .module cpct_sprites -.include "../../../macros/cpct_undocumentedOpcodes.h.s" +.include "../macros/cpct_undocumentedOpcodes.s" ;; ;; ASM bindings for <cpct_spriteColorizeM0> ;; cpct_spriteColorizeM0_asm:: ;; Assembly entry point - ;; GET Parameters from the stack - ld (dms_restore_ix + 2), ix ;; [6] Save IX to restore it before returning - pop hl ;; [3] HL = Return Address + ;; GET Parameters from the stack + ld (dms_restore_ix + 2), ix ;; [6] Save IX to restore it before returning .include /cpct_spriteColorizeM0.asm/ dms_restore_ix: ld ix, #0000 ;; [4] Restore IX before returning - ret ;; [3] Return to caller \ No newline at end of file + ret ;; [3] Return to caller + diff --git a/cpctelera/src/sprites/colorReplace/M0/cpct_spriteColorizeM0_cbindings.s b/cpctelera/src/sprites/colorReplace/M0/cpct_spriteColorizeM0_cbindings.s index 27d164918..4d67122d8 100644 --- a/cpctelera/src/sprites/colorReplace/M0/cpct_spriteColorizeM0_cbindings.s +++ b/cpctelera/src/sprites/colorReplace/M0/cpct_spriteColorizeM0_cbindings.s @@ -18,7 +18,7 @@ ;;------------------------------------------------------------------------------- .module cpct_sprites -.include "../../../macros/cpct_undocumentedOpcodes.h.s" +.include "../macros/cpct_undocumentedOpcodes.s" ;; ;; C bindings for <cpct_spriteColorizeM0> @@ -29,20 +29,19 @@ _cpct_spriteColorizeM0:: ;; GET Parameters from the stack ld (dms_restore_ix + 2), ix ;; [6] Save IX to restore it before returning - pop hl ;; [3] HL = Return Address + pop de ;; [3] DE = Return Address - exx + exx ;; [1] Swap to alternate registers pop hl ;; [3] HL' = Source address (Sprite) pop de ;; [3] DE' = Destination Sprite color pop bc ;; [5] BC' = (B = Sprite Height, C = Width) - exx + exx ;; [1] Swap to default registers - ex (sp), hl ;; [6] HL = (H = newColor, L = oldColor) - ;; ... and leave Return Address at (SP) as we don't need to restore - ;; ... stack status because callin convention is __z88dk_callee + push de ;; [4] Put returning address in the stack again + ;; as this function uses __z88dk_callee convention .include /cpct_spriteColorizeM0.asm/ dms_restore_ix: ld ix, #0000 ;; [4] Restore IX before returning - ret ;; [3] Return to caller \ No newline at end of file + ret ;; [3] Return to caller diff --git a/cpctelera/src/sprites/colorReplace/M0/cpct_spriteMaskedColorizeM0.asm b/cpctelera/src/sprites/colorReplace/M0/cpct_spriteMaskedColorizeM0.asm index 37a32f02e..6ebf9798b 100644 --- a/cpctelera/src/sprites/colorReplace/M0/cpct_spriteMaskedColorizeM0.asm +++ b/cpctelera/src/sprites/colorReplace/M0/cpct_spriteMaskedColorizeM0.asm @@ -1,6 +1,6 @@ ;;-----------------------------LICENSE NOTICE------------------------------------ ;; This file is part of CPCtelera: An Amstrad CPC Game Engine -;; Copyright (C) 2018 Arnaud Bouche (@Arnaud6128) +;; Copyright (C) 2018 Arnaud Bouche (@Arnaud6128)) ;; Copyright (C) 2018 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) ;; ;; This program is free software: you can redistribute it and/or modify @@ -25,15 +25,13 @@ ;; Replace a color in a Masked sprite and copy to another or the same sprite. ;; ;; C Definition: -;; void <cpct_spriteMaskedColorizeM0> (void* *sprite*, void* *spriteColor*, <u8> *width*, <u8> *height*, <u8> *oldColor*, <u8> *newColor*) __z88dk_callee; +;; void <cpct_spriteMaskedColorizeM0> (void* *sprite*, void* *spriteColor*, <u8> *width*, <u8> *height*) __z88dk_callee; ;; ;; Input Parameters (6 bytes): ;; (2B HL') sprite - Source Sprite Pointer (array of pixel data) ;; (2B DE') spriteColor - Destination Sprite Pointer (can be also the Source Sprite) (array of pixel data) ;; (1B C') height - Sprite Height in bytes (>0) ;; (1B B') width - Sprite Width in *bytes* (Beware, *not* in pixels!) -;; (1B L) oldColor - Color to replace -;; (1B H) newColor - New color ;; ;; Assembly call (Input parameters on registers): ;; > call cpct_spriteMaskedColorizeM0_asm @@ -57,19 +55,17 @@ ;; There is no practical upper limit to this value. Height of a sprite in ;; bytes and pixels is the same value, as bytes only group consecutive pixels in ;; the horizontal space. -;; * *oldColor* must be the index of color (0 to 15) to replace -;; * *newColor* must be the index of the new color (0 to 15) ;; ;; Known limitations: ;; * This function *will not work from ROM*, as it uses self-modifying code. ;; * This function requires the CPC firmware to be DISABLED. Otherwise, random crashes might happen due to side effects. ;; ;; Destroyed Register values: -;; AF, BC, DE, HL, BC', DE', HL', IX +;; AF, BC, DE, BC', DE', HL', IX ;; ;; Required memory: -;; C-bindings - 87 bytes -;; ASM-bindings - 73 bytes +;; C-bindings - 165 bytes +;; ASM-bindings - 160 bytes ;; ;; Time Measures: ;; (start code) @@ -92,35 +88,19 @@ ;; Thanks to all of them for their help and support. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -.globl dc_mode0_ct +.globl _cpct_color_old +.globl _cpct_color_new -;; Macro to convert Pixel to xAxC xBxD format -.macro convertPixel - ;; From cpct_px2byteM0 - ld bc, #dc_mode0_ct ;; [3] BC points to conversion table (dc_mode0_ct) - - ;; Compute BC += A - add c ;; [1] | C += A - ld c, a ;; [1] | - sub a ;; [1] A = 0 (preserving Carry Flag) - adc b ;; [1] | B += Carry - ld b, a ;; [1] | - - ;; A = *(BC + A) - ld a, (bc) ;; [2] A = Value stored at the table pointed by BC -.endm - - ;; Convert newColor to pixel format (E) - ld a, h ;; [1] A = H new color index - convertPixel ;; [10] | Convert into A + ;; newColor to pixel format (E) + ld a, (_cpct_color_new);; [4] A = mem new color index ld e, a ;; [1] | E = A new color : xAxC xBxD - ;; Convert oldColor to pixel format (D) - ld a, l ;; [1] A = L old color index - convertPixel ;; [10] | Convert into A + ;; oldColor to pixel format (D) + ld a, (_cpct_color_old);; [4] A = mem old color index ld d, a ;; [1] | D = A old color : xAxC xBxD ld c, #0x55 ;; [2] C = Mask to get pixel A : xAxC xBxD + exx ;; [1] Switch to Alternate registers ld__ixl_c ;; [1] IXL = C (Width) @@ -168,8 +148,8 @@ setByte: inc de ;; [2] Next byte sprite colorized djnz lineLoop ;; [3] Decrement B (Width) if != 0 goto lineLoop - dec c ;; [1] Decrement C (Height) - jr nz, convertLoop ;; [2/3] If C == O goto end + dec c ;; [1] Decrement C (Height) + jr nz, convertLoop ;; [2/3] If C == O goto end end: ;; Return is included in bindings \ No newline at end of file diff --git a/cpctelera/src/sprites/colorReplace/M0/cpct_spriteMaskedColorizeM0_asmbindings.s b/cpctelera/src/sprites/colorReplace/M0/cpct_spriteMaskedColorizeM0_asmbindings.s index 04b8fcf88..af949e8a6 100644 --- a/cpctelera/src/sprites/colorReplace/M0/cpct_spriteMaskedColorizeM0_asmbindings.s +++ b/cpctelera/src/sprites/colorReplace/M0/cpct_spriteMaskedColorizeM0_asmbindings.s @@ -1,6 +1,6 @@ ;;-----------------------------LICENSE NOTICE------------------------------------ ;; This file is part of CPCtelera: An Amstrad CPC Game Engine -;; Copyright (C) 2018 Arnaud Bouche (@Arnaud6128) +;; Copyright (C) 2018 Arnaud Bouche (Arnaud6128) ;; Copyright (C) 2018 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) ;; ;; This program is free software: you can redistribute it and/or modify @@ -18,7 +18,7 @@ ;;------------------------------------------------------------------------------- .module cpct_sprites -.include "../../../macros/cpct_undocumentedOpcodes.h.s" +.include "../macros/cpct_undocumentedOpcodes.s" ;; ;; ASM bindings for <cpct_spriteMaskedColorizeM0> @@ -27,7 +27,6 @@ cpct_spriteMaskedColorizeM0_asm:: ;; Assembly entry point ;; GET Parameters from the stack ld (dms_restore_ix + 2), ix ;; [6] Save IX to restore it before returning - pop hl ;; [3] HL = Return Address .include /cpct_spriteMaskedColorizeM0.asm/ diff --git a/cpctelera/src/sprites/colorReplace/M0/cpct_spriteMaskedColorizeM0_cbindings.s b/cpctelera/src/sprites/colorReplace/M0/cpct_spriteMaskedColorizeM0_cbindings.s index 3dad1ae84..c74a0ea07 100644 --- a/cpctelera/src/sprites/colorReplace/M0/cpct_spriteMaskedColorizeM0_cbindings.s +++ b/cpctelera/src/sprites/colorReplace/M0/cpct_spriteMaskedColorizeM0_cbindings.s @@ -18,7 +18,7 @@ ;;------------------------------------------------------------------------------- .module cpct_sprites -.include "../../../macros/cpct_undocumentedOpcodes.h.s" +.include "../macros/cpct_undocumentedOpcodes.s" ;; ;; C bindings for <cpct_spriteMaskedColorizeM0> @@ -29,7 +29,7 @@ _cpct_spriteMaskedColorizeM0:: ;; GET Parameters from the stack ld (dms_restore_ix + 2), ix ;; [6] Save IX to restore it before returning - pop hl ;; [3] HL = Return Address + pop de ;; [3] DE = Return Address exx pop hl ;; [3] HL' = Source address (Sprite) @@ -37,9 +37,8 @@ _cpct_spriteMaskedColorizeM0:: pop bc ;; [5] BC' = (B = Sprite Height, C = Width) exx - ex (sp), hl ;; [6] HL = (H = newColor, L = oldColor) - ;; ... and leave Return Address at (SP) as we don't need to restore - ;; ... stack status because callin convention is __z88dk_callee + push de ;; [4] Put returning address in the stack again + ;; as this function uses __z88dk_callee convention .include /cpct_spriteMaskedColorizeM0.asm/ diff --git a/cpctelera/src/sprites/colorReplace/colorReplace.h b/cpctelera/src/sprites/colorReplace/colorReplace.h index d5675f624..79cc0f19a 100644 --- a/cpctelera/src/sprites/colorReplace/colorReplace.h +++ b/cpctelera/src/sprites/colorReplace/colorReplace.h @@ -28,17 +28,20 @@ #ifndef CPCT_COLORREPLACE_H #define CPCT_COLORREPLACE_H +// Function to set colors to replace M0 +extern void cpct_setReplaceColorsM0(u8 oldColor, u8 newColor) __z88dk_callee; + // Functions to replace a color in sprite M0 -extern void cpct_spriteColorizeM0(u8* sprite, u8* spriteColor, u8 width, u8 height, u8 oldColor, u8 newColor) __z88dk_callee; -extern void cpct_spriteMaskedColorizeM0(u8* sprite, u8* spriteColor, u8 width, u8 height, u8 oldColor, u8 newColor) __z88dk_callee; +extern void cpct_spriteColorizeM0(u8* sprite, u8* spriteColor, u8 width, u8 height) __z88dk_callee; +extern void cpct_spriteMaskedColorizeM0(u8* sprite, u8* spriteColor, u8 width, u8 height) __z88dk_callee; // Functions to draw a sprite M0 with a color replaced -extern void cpct_drawSpriteColorizeM0(u8* sprite, u8* destMem, u8 width, u8 height, u8 oldColor, u8 newColor) __z88dk_callee; -extern void cpct_drawSpriteMaskedColorizeM0(u8* sprite, u8* destMem, u8 width, u8 height, u8 oldColor, u8 newColor) __z88dk_callee; -extern void cpct_drawSpriteMaskedAlignedColorizeM0(u8* sprite, u8* destMem, u8 width, u8 height, u8 oldColor, u8 newColor, const u8* maskTable) __z88dk_callee; +extern void cpct_drawSpriteColorizeM0(u8* sprite, u8* destMem, u8 width, u8 height) __z88dk_callee; +extern void cpct_drawSpriteMaskedColorizeM0(u8* sprite, u8* destMem, u8 width, u8 height) __z88dk_callee; +extern void cpct_drawSpriteMaskedAlignedColorizeM0(u8* sprite, u8* destMem, u8 width, u8 height, const u8* maskTable) __z88dk_callee; // Functions to replace a color in sprite M1 -extern void cpct_spriteColorizeM1(u8* sprite, u8* spriteColor, u8 width, u8 height, u8 oldColor, u8 newColor) __z88dk_callee; +extern void cpct_spriteColorizeM1(u8* sprite, u8* spriteColor, u8 width, u8 height) __z88dk_callee; extern void cpct_spriteMaskedColorizeM1(u8* sprite, u8* spriteColor, u8 width, u8 height, u8 oldColor, u8 newColor) __z88dk_callee; // Functions to draw a sprite M1 with a color replaced diff --git a/examples/medium/colorReplace/src/drawing.c b/examples/medium/colorReplace/src/drawing.c index 414450594..aa02f4f8a 100644 --- a/examples/medium/colorReplace/src/drawing.c +++ b/examples/medium/colorReplace/src/drawing.c @@ -1,8 +1,8 @@ //-----------------------------LICENSE NOTICE------------------------------------ // This file is part of CPCtelera: An Amstrad CPC Game Engine -// Copyright (C) 2018 Bouche Arnaud (@Arnaud6128) -// Copyright (C) 2018 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) +// Copyright (C) 2017 Bouche Arnaud +// Copyright (C) 2017 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Lesser General Public License as published by @@ -22,104 +22,107 @@ ///////////////////////////////////////////////////////////////////////////////// // GLOBAL VARIABLES -u8 gSpriteColorized[G_BALOON_W*G_BALOON_H]; // Array for sprite to color -u8 gBackGroundColor; // Background color -u8 gBaloonColor; // Current color baloon -u8 gPosCloud; // Position of cloude +u8 gSpriteColorized[G_BALOON_W*G_BALOON_H]; // Array for sprite to color +u8 gBackGroundColor; // Background color +u8 gBaloonColor; // Current color baloon +u8 gPosCloud; // Position of cloude ///////////////////////////////////////////////////////////////////////////////// // STRUCTURES DEFINITION -typedef struct TBaloon // Baloon structure +typedef struct TBaloon // Baloon structure { - i16 posY; // Absolute Baloon PosY (can be outside screen) - u8 posX; // Absolute Baloon PosX - - u8 drawPosY; // In screen Baloon PosY - u8 drawCY; // In screen Baloon Height - - u8 speed; // Baloon speed - u8 color; // Baloon color drawn - - u8 status; // Baloon status ACTIVE / INACTIVE + i16 posY; // Absolute Baloon PosY (can be outside screen) + u8 posX; // Absolute Baloon PosX + + u8 drawPosY; // In screen Baloon PosY + u8 drawCY; // In screen Baloon Height + + u8 speed; // Baloon speed + u8 color; // Baloon color drawn + + u8 status; // Baloon status ACTIVE / INACTIVE } SBaloon; -typedef struct TBaloons // All baloons structure +typedef struct TBaloons // All baloons structure { - u8 nb; // Nb baloons in screen - SBaloon baloons[NB_BALOONS]; // Array of baloon + u8 nb; // Nb baloons in screen + SBaloon baloons[NB_BALOONS]; // Array of baloon } SBaloons; -SBaloons gBaloons; // Baloons to draw +SBaloons gBaloons; // Baloons to draw -typedef struct TStar // Lighting star structure +typedef struct TStar // Lighting star structure { - u8 posX; // Screen PosX - u8 posY; // Screen PosY + u8 posX; // Screen PosX + u8 posY; // Screen PosY - u8 color; // Star color drawn + u8 color; // Star color drawn } SStar; -typedef struct TStars // All stars structure +typedef struct TStars // All stars structure { - SStar stars[NB_STARS]; // Array of stars + SStar stars[NB_STARS]; // Array of stars } SStars; -SStars gStars; // Stars to draw +SStars gStars; // Stars to draw /////////////////////////////////////////////////////// -/// GET RANDOM FROM 0 TO MAX-1 +/// GET RANDOM FROM 0 TO MAX-1 /// u8 GetRand(u8 max) { - return cpct_rand()%max; + return cpct_rand()%max; } /////////////////////////////////////////////////////// -/// CHANGE TWO COLORS OF BALOON SPRITE +/// CHANGE TWO COLORS OF BALOON SPRITE /// void ColorSprite(u8 color) { - // Replace the two colors 1 and 2 of sprite baloon - cpct_spriteColorizeM0(g_baloon, gSpriteColorized, G_BALOON_W, G_BALOON_H, 1, color); // Colors are consecutives - cpct_spriteColorizeM0(gSpriteColorized, gSpriteColorized, G_BALOON_W, G_BALOON_H, 2, color + 1); + // Replace the two colors 1 and 2 of sprite baloon + cpct_setReplaceColorsM0(1, color); + cpct_spriteColorizeM0(g_baloon, gSpriteColorized, G_BALOON_W, G_BALOON_H); // Colors are consecutives + + cpct_setReplaceColorsM0(2, color + 1); + cpct_spriteColorizeM0(gSpriteColorized, gSpriteColorized, G_BALOON_W, G_BALOON_H); } /////////////////////////////////////////////////////// -/// CLEAR BALOON BACKGROUND +/// CLEAR BALOON BACKGROUND /// void ClearBaloon(SBaloon* baloon) { - // If baloon in visible part of view - if (baloon->drawPosY < VIEW_DOWN) - { - u8* pvmem; - - // Compute size to be filled with background color - u8 clearCY = baloon->drawCY + BALOON_TRAIL; - - // Compute position to clear - u8 posDownClearY = baloon->drawPosY + clearCY; - if (posDownClearY > VIEW_DOWN) - clearCY = VIEW_DOWN - baloon->drawPosY; - - // Draw the box with background color to clear - pvmem = GetBackBufferPtr(baloon->posX, baloon->drawPosY); - cpct_drawSolidBox(pvmem, gBackGroundColor, G_BALOON_W, clearCY); - } + // If baloon in visible part of view + if (baloon->drawPosY < VIEW_DOWN) + { + u8* pvmem; + + // Compute size to be filled with background color + u8 clearCY = baloon->drawCY + BALOON_TRAIL; + + // Compute position to clear + u8 posDownClearY = baloon->drawPosY + clearCY; + if (posDownClearY > VIEW_DOWN) + clearCY = VIEW_DOWN - baloon->drawPosY; + + // Draw the box with background color to clear + pvmem = GetBackBufferPtr(baloon->posX, baloon->drawPosY); + cpct_drawSolidBox(pvmem, gBackGroundColor, G_BALOON_W, clearCY); + } } /////////////////////////////////////////////////////// -/// DELETE BALOON +/// DELETE BALOON /// void DeleteBaloons(SBaloon* baloons, SBaloon* baloonToDel, u8* nb) { - // Get last baloon in array - // Decrement number of remaining baloons in array - const SBaloon* lastBaloon = &baloons[--*nb]; - - // Replace baloon to be deleted with last baloon (if they are not the same) - if (baloonToDel != lastBaloon) - cpct_memcpy(baloonToDel, lastBaloon, sizeof(SBaloon)); + // Get last baloon in array + // Decrement number of remaining baloons in array + const SBaloon* lastBaloon = &baloons[--*nb]; + + // Replace baloon to be deleted with last baloon (if they are not the same) + if (baloonToDel != lastBaloon) + cpct_memcpy(baloonToDel, lastBaloon, sizeof(SBaloon)); } /////////////////////////////////////////////////////// @@ -127,85 +130,85 @@ void DeleteBaloons(SBaloon* baloons, SBaloon* baloonToDel, u8* nb) /// void UpdateBaloons() { - SBaloon* itBaloon = gBaloons.baloons; - u8 i; - - // Test if we can add a new baloon - if (gBaloons.nb < NB_BALOONS) - { - // Add new baloon at end of array - // Increment number of baloons in array - SBaloon* newBaloon = &gBaloons.baloons[gBaloons.nb++]; - - // Get random positions X and Y - newBaloon->posX = GetRand(SCREEN_CX - G_BALOON_W); - newBaloon->posY = SCREEN_CY - GetRand(40); - - // Get random speed - newBaloon->speed = GetRand(3) + 2; - - // Get circular next color 2 by 2 until 12 - gBaloonColor = (gBaloonColor + 2) % 12; - newBaloon->color = gBaloonColor + 1; - - // Set baloon ACTIVE - newBaloon->status = BALOON_ACTIVE; - } - - // Update all baloons - for (i = 0; i < gBaloons.nb; i++) - { - // If baloon active move and draw it - if (itBaloon->status == BALOON_ACTIVE) - { - // Test if whole baloon outside view - if (itBaloon->posY + G_BALOON_H < VIEW_TOP) - { - // Set baloon inactive - itBaloon->status = BALOON_INACTIVE; - // Clear baloon background - ClearBaloon(itBaloon); - } - else - { - // Move baloon to up according its speed - i16 posY = itBaloon->posY - itBaloon->speed; - itBaloon->posY = posY; + SBaloon* itBaloon = gBaloons.baloons; + u8 i; + + // Test if we can add a new baloon + if (gBaloons.nb < NB_BALOONS) + { + // Add new baloon at end of array + // Increment number of baloons in array + SBaloon* newBaloon = &gBaloons.baloons[gBaloons.nb++]; + + // Get random positions X and Y + newBaloon->posX = GetRand(SCREEN_CX - G_BALOON_W); + newBaloon->posY = SCREEN_CY - GetRand(40); + + // Get random speed + newBaloon->speed = GetRand(3) + 2; + + // Get circular next color 2 by 2 until 12 + gBaloonColor = (gBaloonColor + 2) % 12; + newBaloon->color = gBaloonColor + 1; + + // Set baloon ACTIVE + newBaloon->status = BALOON_ACTIVE; + } + + // Update all baloons + for (i = 0; i < gBaloons.nb; i++) + { + // If baloon active move and draw it + if (itBaloon->status == BALOON_ACTIVE) + { + // Test if whole baloon outside view + if (itBaloon->posY + G_BALOON_H < VIEW_TOP) + { + // Set baloon inactive + itBaloon->status = BALOON_INACTIVE; + // Clear baloon background + ClearBaloon(itBaloon); + } + else + { + // Move baloon to up according its speed + i16 posY = itBaloon->posY - itBaloon->speed; + itBaloon->posY = posY; - // Baloon outside view by top - if (posY < VIEW_TOP) - { - itBaloon->drawPosY = 0; - itBaloon->drawCY = G_BALOON_H + posY; - } - else - // Baloon outside view by down - if (posY + G_BALOON_H > VIEW_DOWN) - { - itBaloon->drawPosY = posY; - itBaloon->drawCY = VIEW_DOWN - posY; - } - // Baloon all in view - else - { - itBaloon->drawPosY = posY; - itBaloon->drawCY = G_BALOON_H; - } - } - } - // If inactive delete baloon - else - { - // Clear baloon background - ClearBaloon(itBaloon); - - // Delete baloon from list - DeleteBaloons(gBaloons.baloons, itBaloon, &gBaloons.nb); - } - - // Get next baloon pointer - itBaloon++; - } + // Baloon outside view by top + if (posY < VIEW_TOP) + { + itBaloon->drawPosY = 0; + itBaloon->drawCY = G_BALOON_H + posY; + } + else + // Baloon outside view by down + if (posY + G_BALOON_H > VIEW_DOWN) + { + itBaloon->drawPosY = posY; + itBaloon->drawCY = VIEW_DOWN - posY; + } + // Baloon all in view + else + { + itBaloon->drawPosY = posY; + itBaloon->drawCY = G_BALOON_H; + } + } + } + // If inactive delete baloon + else + { + // Clear baloon background + ClearBaloon(itBaloon); + + // Delete baloon from list + DeleteBaloons(gBaloons.baloons, itBaloon, &gBaloons.nb); + } + + // Get next baloon pointer + itBaloon++; + } } /////////////////////////////////////////////////////// @@ -213,27 +216,27 @@ void UpdateBaloons() /// void DrawBaloon(SBaloon* baloon, const u8* spriteBaloon) { - i16 posY = baloon->posY; - - // If baloon in view - if (posY + G_BALOON_H > VIEW_TOP && posY < VIEW_DOWN) - { - // Get VMem pointer of current baloon position - u8* pvmem = GetBackBufferPtr(baloon->posX, baloon->drawPosY); - const u8* sprite = (u8*)spriteBaloon; - - // Baloon partialy outside view by top - if (posY < VIEW_TOP) - { - // Compute Y position - u8 y = -posY; - - // Compute sprite offset - sprite = (u8*)spriteBaloon + G_BALOON_W * y; - } - - cpct_drawSpriteMaskedAlignedTable(sprite, pvmem, G_BALOON_W, baloon->drawCY, gMaskTable); - } + i16 posY = baloon->posY; + + // If baloon in view + if (posY + G_BALOON_H > VIEW_TOP && posY < VIEW_DOWN) + { + // Get VMem pointer of current baloon position + u8* pvmem = GetBackBufferPtr(baloon->posX, baloon->drawPosY); + const u8* sprite = (u8*)spriteBaloon; + + // Baloon partialy outside view by top + if (posY < VIEW_TOP) + { + // Compute Y position + u8 y = -posY; + + // Compute sprite offset + sprite = (u8*)spriteBaloon + G_BALOON_W * y; + } + + cpct_drawSpriteMaskedAlignedTable(sprite, pvmem, G_BALOON_W, baloon->drawCY, gMaskTable); + } } /////////////////////////////////////////////////////// @@ -241,42 +244,45 @@ void DrawBaloon(SBaloon* baloon, const u8* spriteBaloon) /// void DrawStars() { - // Static stars color - const static u8 sColorStar[NB_COLORS_STAR] = { 2, 4, 7, 8, 10, 11, 12 }; - static u8 color = 0; - - u8 i; - for (i = 0; i < NB_STARS; i++) - { - // Get video pointer of each star to be drawn - u8* pvmem = GetBackBufferPtr(gStars.stars[i].posX, gStars.stars[i].posY); - u8 color = gStars.stars[i].color++; - - // Use different drawing color methods - if (i < NB_STARS/3) - { - // Color and draw masked sprite in video memory - cpct_drawSpriteMaskedColorizeM0(g_star_trans, pvmem, G_STAR_TRANS_W, G_STAR_TRANS_H, 15, sColorStar[color]); - } - else if (i > NB_STARS/3 && i < 2*NB_STARS/3) - { - // Color and draw masked aligned sprite in video memory - cpct_drawSpriteMaskedAlignedColorizeM0(g_square, pvmem, G_SQUARE_W, G_SQUARE_H, 15, sColorStar[color], gMaskTable); - } - else - { - // Color and copy masked sprite in temporary array - u8 circleColor[G_CIRCLE_TRANS_W * G_CIRCLE_TRANS_H * 2]; - cpct_spriteMaskedColorizeM0(g_circle_trans, circleColor, G_CIRCLE_TRANS_W, G_CIRCLE_TRANS_H, 15, sColorStar[color]); - - // Draw masked Sprite from temporary array - cpct_drawSpriteMasked(circleColor, pvmem, G_CIRCLE_TRANS_W, G_CIRCLE_TRANS_H); - } - - // If all colors palette used restart from 0 - if (color == NB_COLORS_STAR - 1) - gStars.stars[i].color = 0; - } + // Static stars color + const static u8 sColorStar[NB_COLORS_STAR] = { 2, 4, 7, 8, 10, 11, 12 }; + static u8 color = 0; + + u8 i; + for (i = 0; i < NB_STARS; i++) + { + // Get video pointer of each star to be drawn + u8* pvmem = GetBackBufferPtr(gStars.stars[i].posX, gStars.stars[i].posY); + u8 color = gStars.stars[i].color++; + + // Set color to change + cpct_setReplaceColorsM0(15, sColorStar[color]); + + // Use different drawing color methods + if (i < NB_STARS/3) + { + // Color and draw masked sprite in video memory + cpct_drawSpriteMaskedColorizeM0(g_star_trans, pvmem, G_STAR_TRANS_W, G_STAR_TRANS_H); + } + else if (i > NB_STARS/3 && i < 2*NB_STARS/3) + { + // Color and draw masked aligned sprite in video memory + cpct_drawSpriteMaskedAlignedColorizeM0(g_square, pvmem, G_SQUARE_W, G_SQUARE_H, gMaskTable); + } + else + { + // Color and copy masked sprite in temporary array + u8 circleColor[G_CIRCLE_TRANS_W * G_CIRCLE_TRANS_H * 2]; + cpct_spriteMaskedColorizeM0(g_circle_trans, circleColor, G_CIRCLE_TRANS_W, G_CIRCLE_TRANS_H); + + // Draw masked Sprite from temporary array + cpct_drawSpriteMasked(circleColor, pvmem, G_CIRCLE_TRANS_W, G_CIRCLE_TRANS_H); + } + + // If all colors palette used restart from 0 + if (color == NB_COLORS_STAR - 1) + gStars.stars[i].color = 0; + } } /////////////////////////////////////////////////////// @@ -284,9 +290,9 @@ void DrawStars() /// void DrawCloud() { - // Draw cloud at fixed place - u8* pvmem = GetBackBufferPtr(0, POS_CLOUD_Y); - cpct_drawSprite(g_cloud, pvmem, G_CLOUD_W, G_CLOUD_H); + // Draw cloud at fixed place + u8* pvmem = GetBackBufferPtr(0, POS_CLOUD_Y); + cpct_drawSprite(g_cloud, pvmem, G_CLOUD_W, G_CLOUD_H); } /////////////////////////////////////////////////////// @@ -294,35 +300,40 @@ void DrawCloud() /// void DrawSceneBaloons() { - u8 i; - - // Clear background for all baloons - SBaloon* itBaloon = gBaloons.baloons; // Get first baloon pointer - for (i = 0; i < gBaloons.nb; i++) - { - ClearBaloon(itBaloon); - itBaloon++; - } - - // Draw sprite cloud - DrawCloud(); - - // Draw all baloons - itBaloon = gBaloons.baloons; // Get first baloon pointer - for (i = 0; i < gBaloons.nb; i++) - { - const u8* sprite = g_baloon; // Default baloon sprite (blue) + u8 i, color = 0; + + // Clear background for all baloons + SBaloon* itBaloon = gBaloons.baloons; // Get first baloon pointer + for (i = 0; i < gBaloons.nb; i++) + { + ClearBaloon(itBaloon); + itBaloon++; + } + + // Draw sprite cloud + DrawCloud(); + + // Draw all baloons + itBaloon = gBaloons.baloons; // Get first baloon pointer + for (i = 0; i < gBaloons.nb; i++) + { + const u8* sprite = g_baloon; // Default baloon sprite (blue) - // Test if sprite have colors to change - if (itBaloon->color > 1) // Color 0 (white) is transparent color - { - ColorSprite(itBaloon->color); // Change colors of ballon - sprite = gSpriteColorized; // Sprite to draw is colorized baloon - } - - DrawBaloon(itBaloon, sprite); // Draw baloon sprite - itBaloon++; // Get next baloon - } + // Test if sprite have colors to change + if (itBaloon->color > 1) // Color 0 (white) is transparent color + { + if (color != itBaloon->color) // Test if need to change Color of Sprite + { + color = itBaloon->color; + ColorSprite(color); // Change colors of ballon + } + + sprite = gSpriteColorized; // Sprite to draw is colorized baloon + } + + DrawBaloon(itBaloon, sprite); // Draw baloon sprite + itBaloon++; // Get next baloon + } } /////////////////////////////////////////////////////// @@ -330,21 +341,21 @@ void DrawSceneBaloons() /// void DrawBackground() { - u8* pvmem; - - // Fill video buffer with background color - cpct_memset((u8*)SCREEN_BUFF, gBackGroundColor, VMEM_SIZE); - - // Draw left part of Roof - pvmem = GetBackBufferPtr(0, SCREEN_CY-G_ROOF_H); - cpct_drawSprite(g_roof, pvmem, G_ROOF_W, G_ROOF_H); - - // Draw right part of Roof - pvmem += G_ROOF_W; - cpct_drawSprite(g_roof, pvmem, G_ROOF_W, G_ROOF_H); - - // Copy Same background on both buffers - cpct_memcpy(CPCT_VMEM_START, (u8*)SCREEN_BUFF, VMEM_SIZE); + u8* pvmem; + + // Fill video buffer with background color + cpct_memset((u8*)SCREEN_BUFF, gBackGroundColor, VMEM_SIZE); + + // Draw left part of Roof + pvmem = GetBackBufferPtr(0, SCREEN_CY-G_ROOF_H); + cpct_drawSprite(g_roof, pvmem, G_ROOF_W, G_ROOF_H); + + // Draw right part of Roof + pvmem += G_ROOF_W; + cpct_drawSprite(g_roof, pvmem, G_ROOF_W, G_ROOF_H); + + // Copy Same background on both buffers + cpct_memcpy(CPCT_VMEM_START, (u8*)SCREEN_BUFF, VMEM_SIZE); } ///////////////////////////////////////////////////////////////////////////////// @@ -354,18 +365,18 @@ void DrawBackground() /// void InitializeDrawing() { - u8 dx = SCREEN_CX / NB_STARS; // Compute space between stars - - u8 i; - for (i = 0; i < NB_STARS; i++) - { - gStars.stars[i].posX = dx * i + 5; // Constant space beetween stars - gStars.stars[i].posY = GetRand(10) + 175; // Random Y position from 175 to 184 - gStars.stars[i].color = GetRand(NB_COLORS_STAR); // Random color from 0 to NB_COLORS_STAR-1 - } - - gBackGroundColor = cpct_px2byteM0(14, 14); // Get byte color of background for M0 - gBaloons.nb = 0; // No baloon to draw at start - - DrawBackground(); // Set background on both buffers + u8 dx = SCREEN_CX / NB_STARS; // Compute space between stars + + u8 i; + for (i = 0; i < NB_STARS; i++) + { + gStars.stars[i].posX = dx * i + 5; // Constant space beetween stars + gStars.stars[i].posY = GetRand(10) + 175; // Random Y position from 175 to 184 + gStars.stars[i].color = GetRand(NB_COLORS_STAR); // Random color from 0 to NB_COLORS_STAR-1 + } + + gBackGroundColor = cpct_px2byteM0(14, 14); // Get byte color of background for M0 + gBaloons.nb = 0; // No baloon to draw at start + + DrawBackground(); // Set background on both buffers } From 07a09813d2cb6cbbef3a679afc3c731b5e520e23 Mon Sep 17 00:00:00 2001 From: ronaldo <ronaldo@cheesetea.com> Date: Fri, 26 Jan 2018 23:41:10 +0100 Subject: [PATCH 23/31] Added new asm macro for accessing Look-Up-Tables --- cpctelera/src/macros/allmacros.h.s | 1 + cpctelera/src/macros/cpct_luts.h.s | 79 ++++++++++++++++++++++++++++++ 2 files changed, 80 insertions(+) create mode 100644 cpctelera/src/macros/cpct_luts.h.s diff --git a/cpctelera/src/macros/allmacros.h.s b/cpctelera/src/macros/allmacros.h.s index cc2010584..e46d741c4 100644 --- a/cpctelera/src/macros/allmacros.h.s +++ b/cpctelera/src/macros/allmacros.h.s @@ -20,6 +20,7 @@ .include "macros/cpct_opcodeConstants.h.s" .include "macros/cpct_reverseBits.h.s" .include "macros/cpct_undocumentedOpcodes.h.s" +.include "macros/cpct_tableConversions.h.s" ;;////////////////////////////////////////////////////////////////////// ;; Group: General Useful Macros diff --git a/cpctelera/src/macros/cpct_luts.h.s b/cpctelera/src/macros/cpct_luts.h.s new file mode 100644 index 000000000..1747d4680 --- /dev/null +++ b/cpctelera/src/macros/cpct_luts.h.s @@ -0,0 +1,79 @@ +;;-----------------------------LICENSE NOTICE------------------------------------ +;; This file is part of CPCtelera: An Amstrad CPC Game Engine +;; Copyright (C) 2018 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) +;; +;; This program is free software: you can redistribute it and/or modify +;; it under the terms of the GNU Lesser General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU Lesser General Public License for more details. +;; +;; You should have received a copy of the GNU Lesser General Public License +;; along with this program. If not, see <http://www.gnu.org/licenses/>. +;;------------------------------------------------------------------------------- + +;; +;; File: LUTs (Look-Up-Tables) +;; +;; Useful macros for accessing and managing Look-Up-Tables +;; + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Macro: cpctm_lutget8 +;; +;; Gets a value from a 256-byte-max 8-bit table into A register +;; +;; Parameters: +;; Table - Memory address where the 256-byte-max table starts. It can be +;; either an hexadecimal, decimal or octal address, or a symbol (the table name). +;; TR1 - An 8-bits register from the set {B, D, H} +;; TR2 - An 8-bits register from the set {C, E, L}. This register must +;; match TR1 to form a valid 16-bits register (BC, DE or HL), as the register TR1'TR2 +;; will be loaded with the address of the table, to be the base pointer. +;; +;; Input Registers: +;; A - Index in the LUT to be accessed. +;; +;; Return Value: +;; A - Value got from the LUT ( table[TR1'TR2 + A] ) +;; +;; Details: +;; This macro gets a value from a table into the A register. The process is simple: +;; +;; 1. It loads the address of the table in the 16-bits register TR1'TR2 +;; 2. It adds the index (A) to TR1'TR2 (TR1'TR2 += A) +;; 3. It loads into A register the byte pointed by TR1'TR2 +;; +;; Modified Registers: +;; AF, TR1, TR2 +;; +;; Required memory: +;; 9 bytes +;; +;; Time Measures: +;; (start code) +;; Case | microSecs(us) | CPU Cycles +;; ------------------------------------ +;; Any | 10 | 40 +;; ------------------------------------ +;; (end code) +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +.macro cpctm_lutget8 Table, TR1, TR2 + ld TR1'TR2, #Table ;; [3] TR1_TR2 points to the LUT + + ;; Compute TR1'TR2 += A + add TR2 ;; [1] | TR2 += A + ld TR2, a ;; [1] | + sub a ;; [1] A = 0 (preserving Carry Flag) + adc TR1 ;; [1] | TR1 += Carry + ld TR1, a ;; [1] | + + ;; A = *(TR1_TR2 + A) + ld a, (TR1'TR2) ;; [2] A = Value stored at given index from the LUT +.endm + From 2821498ad18996e385a3f052b28e940eef917449 Mon Sep 17 00:00:00 2001 From: ronaldo <ronaldo@cheesetea.com> Date: Sat, 27 Jan 2018 01:26:20 +0100 Subject: [PATCH 24/31] Modified allmacros.h.s to properly include luts --- cpctelera/src/macros/allmacros.h.s | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpctelera/src/macros/allmacros.h.s b/cpctelera/src/macros/allmacros.h.s index e46d741c4..956570562 100644 --- a/cpctelera/src/macros/allmacros.h.s +++ b/cpctelera/src/macros/allmacros.h.s @@ -20,7 +20,7 @@ .include "macros/cpct_opcodeConstants.h.s" .include "macros/cpct_reverseBits.h.s" .include "macros/cpct_undocumentedOpcodes.h.s" -.include "macros/cpct_tableConversions.h.s" +.include "macros/cpct_luts.h.s" ;;////////////////////////////////////////////////////////////////////// ;; Group: General Useful Macros From f113038c9896e3e1ffb181989ef12765dbf6ff53 Mon Sep 17 00:00:00 2001 From: ronaldo <ronaldo@cheesetea.com> Date: Sat, 27 Jan 2018 02:11:16 +0100 Subject: [PATCH 25/31] Created fast split version of spriteColourizeM0 * One function sets colours, the other does the replacement --- .../M0/cpct_setSpriteColourizeM0_f.asm | 98 +++++++++++++ .../cpct_setSpriteColourizeM0_f_asmbindings.s | 28 ++++ .../cpct_setSpriteColourizeM0_f_cbindings.s | 35 +++++ .../M0/cpct_spriteColourizeM0_f.asm | 137 ++++++++++++++++++ .../M0/cpct_spriteColourizeM0_f_asmbindings.s | 28 ++++ .../M0/cpct_spriteColourizeM0_f_cbindings.s | 36 +++++ 6 files changed, 362 insertions(+) create mode 100644 cpctelera/src/sprites/colorReplace/M0/cpct_setSpriteColourizeM0_f.asm create mode 100644 cpctelera/src/sprites/colorReplace/M0/cpct_setSpriteColourizeM0_f_asmbindings.s create mode 100644 cpctelera/src/sprites/colorReplace/M0/cpct_setSpriteColourizeM0_f_cbindings.s create mode 100644 cpctelera/src/sprites/colorReplace/M0/cpct_spriteColourizeM0_f.asm create mode 100644 cpctelera/src/sprites/colorReplace/M0/cpct_spriteColourizeM0_f_asmbindings.s create mode 100644 cpctelera/src/sprites/colorReplace/M0/cpct_spriteColourizeM0_f_cbindings.s diff --git a/cpctelera/src/sprites/colorReplace/M0/cpct_setSpriteColourizeM0_f.asm b/cpctelera/src/sprites/colorReplace/M0/cpct_setSpriteColourizeM0_f.asm new file mode 100644 index 000000000..b87415992 --- /dev/null +++ b/cpctelera/src/sprites/colorReplace/M0/cpct_setSpriteColourizeM0_f.asm @@ -0,0 +1,98 @@ +;;-----------------------------LICENSE NOTICE------------------------------------ +;; This file is part of CPCtelera: An Amstrad CPC Game Engine +;; Copyright (C) 2018 Arnaud Bouche (@Arnaud6128) +;; Copyright (C) 2018 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) +;; +;; This program is free software: you can redistribute it and/or modify +;; it under the terms of the GNU Lesser General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU Lesser General Public License for more details. +;; +;; You should have received a copy of the GNU Lesser General Public License +;; along with this program. If not, see <http://www.gnu.org/licenses/>. +;;------------------------------------------------------------------------------- +.module cpct_sprites + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; +;; Function: cpct_setSpriteColourizeM0_f +;; +;; Sets the concrete colour that will be replaced by <cpct_spriteColourizeM0_f> when called. +;; +;; C Definition: +;; void <cpct_setSpriteColourizeM0_f> (<u8> *oldColor*, <u8> *newColor*) __z88dk_callee; +;; +;; Input Parameters (6 bytes): +;; (1B L ) oldColor - Colour to be replaced (Palette Index, 0-15) +;; (1B H ) newColor - New colour (Palette Index, 0-15) +;; +;; Assembly call (Input parameters on registers): +;; > call cpct_setSpriteColourizeM0_f_asm +;; +;; Parameter Restrictions: +;; * *oldColor* must be the palette index of the colour to be replaced (0 to 15). +;; * *newColor* must be the palette index of the new colour (0 to 15). +;; +;; Known limitations: +;; * This function *will not work from ROM*, as it uses self-modifying code. +;; +;; Details: +;; <TODO> +;; +;; Destroyed Register values: +;; A, BC, HL +;; +;; Required memory: +;; C-bindings - 37 bytes +;; ASM-bindings - 35 bytes +;; +;; Time Measures: +;; (start code) +;; Case | microSecs (us) | CPU Cycles +;; ---------------------------------------------------------------- +;; Any | 52 | 208 +;; ---------------------------------------------------------------- +;; Asm saving | -9 | -36 +;; ---------------------------------------------------------------- +;; (end code) +;; W = *width* in bytes, H = *height* in bytes +;; +;; Credits: +;; Original routine optimized by @Docent and discussed in CPCWiki : +;; http://www.cpcwiki.eu/forum/programming/cpctelera-colorize-sprite/ +;; +;; Thanks to all of them for their help and support. +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +.globl dc_mode0_ct ;; Look-Up-Table to convert Palette Indexes to 4-bits pixel 1 screen format patterns +.include "macros/cpct_luts.h.s" ;; Macros to easily access the Look-Up-Table +;; Symbols for placeholders inside the Colourize function +.globl cpct_spriteColourizeM0_px1_newval +.globl cpct_spriteColourizeM0_px0_newval +.globl cpct_spriteColourizeM0_px1_oldval +.globl cpct_spriteColourizeM0_px0_oldval + + ;; Use Look-Up-Table to convert palette index colour to screen pixel format + ;; This conversion is for the Pixel 1 into the two pixels each byte has in mode 0 [0,1] + ;; Therefore, only bits x0x2x1x3 will be produced. + + ;; Convert newColour to pixel format + ld a, h ;; [1] A = H new colour index + cpctm_lutget8 dc_mode0_ct, b, c ;; [10] Get from Look-Up-Table dc_mode0_ct[BC + A] + ld (cpct_spriteColourizeM0_px1_newval), a ;; [4] Write Pixel 1 format (x0x2x1x3) into Colourize function code + rlca ;; [1] Convert Pixel 1 format to Pixel 0, shifting bits to the left + ld (cpct_spriteColourizeM0_px0_newval), a ;; [4] Write Pixel 0 format (0x2x1x3x) into Colourize function code + + ;; Convert oldColour to pixel format + ld a, l ;; [1] A = L old colour index + cpctm_lutget8 dc_mode0_ct, b, c ;; [10] Get from Look-Up-Table dc_mode0_ct[BC + A] + ld (cpct_spriteColourizeM0_px1_oldval), a ;; [4] Write Pixel 1 format (x0x2x1x3) into Colourize function code + rlca ;; [1] Convert Pixel 1 format to Pixel 0, shifting bits to the left + ld (cpct_spriteColourizeM0_px0_oldval), a ;; [4] Write Pixel 0 format (0x2x1x3x) into Colourize function code + +ret ;; [3] Return to the caller diff --git a/cpctelera/src/sprites/colorReplace/M0/cpct_setSpriteColourizeM0_f_asmbindings.s b/cpctelera/src/sprites/colorReplace/M0/cpct_setSpriteColourizeM0_f_asmbindings.s new file mode 100644 index 000000000..5db953ec9 --- /dev/null +++ b/cpctelera/src/sprites/colorReplace/M0/cpct_setSpriteColourizeM0_f_asmbindings.s @@ -0,0 +1,28 @@ +;;-----------------------------LICENSE NOTICE------------------------------------ +;; This file is part of CPCtelera: An Amstrad CPC Game Engine +;; Copyright (C) 2018 Arnaud Bouche (@Arnaud6128) +;; Copyright (C) 2018 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) +;; +;; This program is free software: you can redistribute it and/or modify +;; it under the terms of the GNU Lesser General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU Lesser General Public License for more details. +;; +;; You should have received a copy of the GNU Lesser General Public License +;; along with this program. If not, see <http://www.gnu.org/licenses/>. +;;------------------------------------------------------------------------------- +.module cpct_sprites + +.include "macros/cpct_undocumentedOpcodes.h.s" + +;; +;; ASM bindings for <cpct_spriteColourizeM0> +;; +cpct_setSpriteColourizeM0_f_asm:: ;; Assembly entry point + +.include /cpct_setSpriteColourizeM0_f.asm/ diff --git a/cpctelera/src/sprites/colorReplace/M0/cpct_setSpriteColourizeM0_f_cbindings.s b/cpctelera/src/sprites/colorReplace/M0/cpct_setSpriteColourizeM0_f_cbindings.s new file mode 100644 index 000000000..7abe81e14 --- /dev/null +++ b/cpctelera/src/sprites/colorReplace/M0/cpct_setSpriteColourizeM0_f_cbindings.s @@ -0,0 +1,35 @@ +;;-----------------------------LICENSE NOTICE------------------------------------ +;; This file is part of CPCtelera: An Amstrad CPC Game Engine +;; Copyright (C) 2018 Arnaud Bouche (@Arnaud6128) +;; Copyright (C) 2018 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) +;; +;; This program is free software: you can redistribute it and/or modify +;; it under the terms of the GNU Lesser General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU Lesser General Public License for more details. +;; +;; You should have received a copy of the GNU Lesser General Public License +;; along with this program. If not, see <http://www.gnu.org/licenses/>. +;;------------------------------------------------------------------------------- +.module cpct_sprites + +.include "macros/cpct_undocumentedOpcodes.h.s" + +;; +;; C bindings for <cpct_setSpriteColourizeM0_f> +;; +;; 9 us, 2 bytes +;; +_cpct_setSpriteColourizeM0_f:: + ;; GET Parameters from the stack + pop hl ;; [3] HL = Return Address + ex (sp), hl ;; [6] H = newColour, L = oldColour + ;; ... and leave Return Address at (SP) as we don't need to restore + ;; ... stack status because callin convention is __z88dk_callee + +.include /cpct_setSpriteColourizeM0_f.asm/ diff --git a/cpctelera/src/sprites/colorReplace/M0/cpct_spriteColourizeM0_f.asm b/cpctelera/src/sprites/colorReplace/M0/cpct_spriteColourizeM0_f.asm new file mode 100644 index 000000000..472cafb3a --- /dev/null +++ b/cpctelera/src/sprites/colorReplace/M0/cpct_spriteColourizeM0_f.asm @@ -0,0 +1,137 @@ +;;-----------------------------LICENSE NOTICE------------------------------------ +;; This file is part of CPCtelera: An Amstrad CPC Game Engine +;; Copyright (C) 2018 Arnaud Bouche (@Arnaud6128) +;; Copyright (C) 2018 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) +;; +;; This program is free software: you can redistribute it and/or modify +;; it under the terms of the GNU Lesser General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU Lesser General Public License for more details. +;; +;; You should have received a copy of the GNU Lesser General Public License +;; along with this program. If not, see <http://www.gnu.org/licenses/>. +;;------------------------------------------------------------------------------- +.module cpct_sprites + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; +;; Function: cpct_spriteColourizeM0_f +;; +;; Replace one concrete colour of a sprite by a different one. This function +;; does the replacement, use <cpct_setSpriteColourizeM0_f> to pick up colours. +;; +;; C Definition: +;; void <cpct_spriteColourizeM0_f> (<u8> *width*, <u8> *height*, void* *sprite*) __z88dk_callee; +;; +;; Input Parameters (6 bytes): +;; (2B HL) sprite - Source Sprite Pointer (array of pixel data) +;; (1B C ) height - Sprite Height in bytes (>0) +;; (1B B ) width - Sprite Width in *bytes* (Beware, *not* in pixels!) +;; +;; Assembly call (Input parameters on registers): +;; > call cpct_spriteColourizeM0_f_asm +;; +;; Parameter Restrictions: +;; * *sprite* must be a pointer to the start of an array containing sprite's pixels data +;; in screen pixel format. Sprite must be rectangular and all bytes in the array must be +;; consecutive pixels, starting from top-left corner and going left-to-right, top-to-bottom +;; down to the bottom-right corner. Total amount of bytes in pixel array should be *width* x *height*. +;; * *width* must be the width of the sprite *in bytes*. Always remember that the width must be +;; expressed in bytes and *not* in pixels. +;; * *height* must be the height of the sprite in bytes, and must be greater than 0. +;; There is no practical upper limit to this value. Height of a sprite in +;; bytes and pixels is the same value, as bytes only group consecutive pixels in +;; the horizontal space. +;; +;; Details: +;; <TODO> +;; +;; Known limitations: +;; * This function *will not work from ROM*, as it uses self-modifying code. +;; +;; Destroyed Register values: +;; AF, BC, DE, HL +;; +;; Required memory: +;; C-bindings - 38 bytes +;; ASM-bindings - 35 bytes +;; +;; Time Measures: +;; (start code) +;; Case | microSecs (us) | CPU Cycles +;; ---------------------------------------------------------------- +;; Best Case | 21 + (5 + 27W)H | 84 + (20 + 108W)H +;; Worst Case | 21 + (5 + 29W)H | 84 + (20 + 116W)H +;; ---------------------------------------------------------------- +;; W=2,H=16 | 965 / 1029 | 3860 / 4116 +;; W=4,H=32 | 3637 / 3893 | 14548 / 15572 +;; ---------------------------------------------------------------- +;; Asm saving | -12 | -48 +;; ---------------------------------------------------------------- +;; (end code) +;; W = *width* in bytes, H = *height* in bytes +;; +;; Credits: +;; Original routine optimized by @Docent and discussed in CPCWiki : +;; http://www.cpcwiki.eu/forum/programming/cpctelera-colorize-sprite/ +;; +;; Thanks to all of them for their help and support. +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;; Save width value to restore it after each line +ld a, b ;; [1] A = width +ld (w_restore), a ;; [4] Save width into its restore place + +;; As E register is free, use it as a cache for Pixel 1 Pattern of the colour to be replaced +px1_oldval = .+1 +ld e, #00 ;; [2] E = Pixel 1 4-bit Pattern of the colour to be replaced (x0x2x1x3) + +;; Loop through all the bytes of the sprite, replacing colours that have the same +;; 4-bit pattern of the colour we want to replace. +loop: + ;; Check and replace Pixel 1 + ld a, (hl) ;; [2] A = Byte with 2 Mode 0 Pixels to be replaced + and #0b01010101 ;; [2] A ^= 0x55. Left out only the 4 bits of the Pixel 1 (x0x2x1x3) + ld d, a ;; [1] D = holds a copy of Pixel 1 bits, just in case we don't have to replace it + cp e ;; [1] A == E? Check if A is equal to the Pixel 1 Pattern of the colour we want to replace + jr nz, notpx1 ;; [2/3] If it is not equal, just continue to check pixel 0 + px1_newval = .+1 + ld d, #00 ;; [2] Perform replacement of Pixel 1. D holds the 4 bits of the new colour. #00 is a placeholder + notpx1: + + ;; Check and replace Pixel 0 + ld a, (hl) ;; [2] A = Restore the value of the byte with the 2 Mode 0 pixels to be replaced + and #0b10101010 ;; [2] A ^= 0xAA. Left out only the 4 bits of the Pixel 0 (0x2x1x3x) + px0_oldval = .+1 + cp #00 ;; [2] Check if A is equal to the Pixel 0 Pattern of the colour we want to replace. #00 is a placeholder + jr nz, notpx0 ;; [2/3] If it is not equal, just continue to mix both output values + px0_newval = .+1 + ld a, #00 ;; [2] Perform replacement of Pixel 0. A holds the 4 bits of the new colour. #00 is a placeholder + notpx0: + + ;; Mix both replacements and save + or d ;; [1] A |= C. A and C hold replacements for pixels 0 and 1. This mixes them into A. + ld (hl), a ;; [2] Write byte with colours replaced + inc hl ;; [2] HL++ Move to next byte of the sprite + + djnz loop ;; [3/4] B--. Continue looping if there are more bytes left in this sprite line (B!=0) + + w_restore=.+1 + ld b, #00 ;; [2] B = width (restore value). #00 is a placeholder + dec c ;; [1] C-- (One less line of the sprite to process) + jr nz, loop ;; [2/3] Continue looping if there are more lines left + + ret ;; [3] Return to caller + +;; +;; Global symbols to be used by external functions to set placeholders +;; +cpct_spriteColourizeM0_px0_oldval == px0_oldval +cpct_spriteColourizeM0_px1_oldval == px1_oldval +cpct_spriteColourizeM0_px0_newval == px0_newval +cpct_spriteColourizeM0_px1_newval == px1_newval diff --git a/cpctelera/src/sprites/colorReplace/M0/cpct_spriteColourizeM0_f_asmbindings.s b/cpctelera/src/sprites/colorReplace/M0/cpct_spriteColourizeM0_f_asmbindings.s new file mode 100644 index 000000000..00053edc2 --- /dev/null +++ b/cpctelera/src/sprites/colorReplace/M0/cpct_spriteColourizeM0_f_asmbindings.s @@ -0,0 +1,28 @@ +;;-----------------------------LICENSE NOTICE------------------------------------ +;; This file is part of CPCtelera: An Amstrad CPC Game Engine +;; Copyright (C) 2018 Arnaud Bouche (@Arnaud6128) +;; Copyright (C) 2018 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) +;; +;; This program is free software: you can redistribute it and/or modify +;; it under the terms of the GNU Lesser General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU Lesser General Public License for more details. +;; +;; You should have received a copy of the GNU Lesser General Public License +;; along with this program. If not, see <http://www.gnu.org/licenses/>. +;;------------------------------------------------------------------------------- +.module cpct_sprites + +.include "macros/cpct_undocumentedOpcodes.h.s" + +;; +;; ASM bindings for <cpct_spriteColourizeM0> +;; +cpct_spriteColourizeM0_f_asm:: ;; Assembly entry point + +.include /cpct_spriteColourizeM0_f.asm/ diff --git a/cpctelera/src/sprites/colorReplace/M0/cpct_spriteColourizeM0_f_cbindings.s b/cpctelera/src/sprites/colorReplace/M0/cpct_spriteColourizeM0_f_cbindings.s new file mode 100644 index 000000000..c382388de --- /dev/null +++ b/cpctelera/src/sprites/colorReplace/M0/cpct_spriteColourizeM0_f_cbindings.s @@ -0,0 +1,36 @@ +;;-----------------------------LICENSE NOTICE------------------------------------ +;; This file is part of CPCtelera: An Amstrad CPC Game Engine +;; Copyright (C) 2018 Arnaud Bouche (@Arnaud6128) +;; Copyright (C) 2018 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) +;; +;; This program is free software: you can redistribute it and/or modify +;; it under the terms of the GNU Lesser General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU Lesser General Public License for more details. +;; +;; You should have received a copy of the GNU Lesser General Public License +;; along with this program. If not, see <http://www.gnu.org/licenses/>. +;;------------------------------------------------------------------------------- +.module cpct_sprites + +.include "macros/cpct_undocumentedOpcodes.h.s" + +;; +;; C bindings for <cpct_spriteColourizeM0_f> +;; +;; 12 us, 3 bytes +;; +_cpct_spriteColourizeM0_f:: + ;; GET Parameters from the stack + pop hl ;; [3] HL = Return Address + pop bc ;; [3] B = Width, C = Height + ex (sp), hl ;; [6] HL = Pointer to the sprite + ;; ... and leave Return Address at (SP) as we don't need to restore + ;; ... stack status because callin convention is __z88dk_callee + +.include /cpct_spriteColourizeM0_f.asm/ From 8426f2525cbff5db4232724fa4e8cf24520d96a8 Mon Sep 17 00:00:00 2001 From: ronaldo <ronaldo@cheesetea.com> Date: Sat, 27 Jan 2018 02:12:51 +0100 Subject: [PATCH 26/31] Added new functions to colorReplace.h --- cpctelera/src/sprites/colorReplace/colorReplace.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/cpctelera/src/sprites/colorReplace/colorReplace.h b/cpctelera/src/sprites/colorReplace/colorReplace.h index d5675f624..a1e70b731 100644 --- a/cpctelera/src/sprites/colorReplace/colorReplace.h +++ b/cpctelera/src/sprites/colorReplace/colorReplace.h @@ -28,6 +28,9 @@ #ifndef CPCT_COLORREPLACE_H #define CPCT_COLORREPLACE_H +extern void cpct_setSpriteColourizeM0_f(u8 oldColour, u8 newColour) __z88dk_callee; +extern void cpct_spriteColourizeM0_f(u8 width, u8 height, u8 *sprite) __z88dk_callee; + // Functions to replace a color in sprite M0 extern void cpct_spriteColorizeM0(u8* sprite, u8* spriteColor, u8 width, u8 height, u8 oldColor, u8 newColor) __z88dk_callee; extern void cpct_spriteMaskedColorizeM0(u8* sprite, u8* spriteColor, u8 width, u8 height, u8 oldColor, u8 newColor) __z88dk_callee; From be68a92bf5a04b1c3682ad6318b3e17bb81423ff Mon Sep 17 00:00:00 2001 From: ronaldo <ronaldo@cheesetea.com> Date: Sat, 27 Jan 2018 02:13:58 +0100 Subject: [PATCH 27/31] Added gitignore to colorReplace example --- examples/medium/colorReplace/.gitignore | 1 + 1 file changed, 1 insertion(+) create mode 100644 examples/medium/colorReplace/.gitignore diff --git a/examples/medium/colorReplace/.gitignore b/examples/medium/colorReplace/.gitignore new file mode 100644 index 000000000..f9e0cbe8a --- /dev/null +++ b/examples/medium/colorReplace/.gitignore @@ -0,0 +1 @@ +src/sprites/ From 6d08814ab143c7288437914ca8860cfe6dccd599 Mon Sep 17 00:00:00 2001 From: ronaldo <ronaldo@cheesetea.com> Date: Sat, 27 Jan 2018 02:14:49 +0100 Subject: [PATCH 28/31] Used new functions in the example --- examples/medium/colorReplace/src/drawing.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/examples/medium/colorReplace/src/drawing.c b/examples/medium/colorReplace/src/drawing.c index 414450594..4cf6a249d 100644 --- a/examples/medium/colorReplace/src/drawing.c +++ b/examples/medium/colorReplace/src/drawing.c @@ -80,8 +80,13 @@ u8 GetRand(u8 max) void ColorSprite(u8 color) { // Replace the two colors 1 and 2 of sprite baloon - cpct_spriteColorizeM0(g_baloon, gSpriteColorized, G_BALOON_W, G_BALOON_H, 1, color); // Colors are consecutives - cpct_spriteColorizeM0(gSpriteColorized, gSpriteColorized, G_BALOON_W, G_BALOON_H, 2, color + 1); + //cpct_spriteColorizeM0(g_baloon, gSpriteColorized, G_BALOON_W, G_BALOON_H, 1, color); // Colors are consecutives + //cpct_spriteColorizeM0(gSpriteColorized, gSpriteColorized, G_BALOON_W, G_BALOON_H, 2, color + 1); + cpct_memcpy(gSpriteColorized, g_baloon, G_BALOON_H*G_BALOON_W); + cpct_setSpriteColourizeM0_f(1, color); + cpct_spriteColourizeM0_f(G_BALOON_W, G_BALOON_H, gSpriteColorized); + cpct_setSpriteColourizeM0_f(2, color + 1); + cpct_spriteColourizeM0_f(G_BALOON_W, G_BALOON_H, gSpriteColorized); } /////////////////////////////////////////////////////// From 869a54a721826f69b87021bc751aca8a842b126f Mon Sep 17 00:00:00 2001 From: Arnaud <arnaud_bouche@hotmail.com> Date: Sat, 27 Jan 2018 10:20:53 +0100 Subject: [PATCH 29/31] Revert "Add new function cpct_setReplaceColors and update others" This reverts commit 04a34248f2969c862be31b1ed0941bf7a2d430a7. --- .../M0/cpct_drawSpriteColorizeM0.asm | 41 +- .../cpct_drawSpriteColorizeM0_asmbindings.s | 7 +- .../M0/cpct_drawSpriteColorizeM0_cbindings.s | 15 +- ...cpct_drawSpriteMaskedAlignedColorizeM0.asm | 149 ++--- ...priteMaskedAlignedColorizeM0_asmbindings.s | 7 +- ...wSpriteMaskedAlignedColorizeM0_cbindings.s | 17 +- .../M0/cpct_drawSpriteMaskedColorizeM0.asm | 56 +- ...t_drawSpriteMaskedColorizeM0_asmbindings.s | 3 +- ...pct_drawSpriteMaskedColorizeM0_cbindings.s | 11 +- .../colorReplace/M0/cpct_replaceColor.s | 44 -- .../M0/cpct_setReplaceColorsM0.asm | 87 --- .../M0/cpct_setReplaceColorsM0_cbinding.s | 31 -- .../colorReplace/M0/cpct_spriteColorizeM0.asm | 57 +- .../M0/cpct_spriteColorizeM0_asmbindings.s | 10 +- .../M0/cpct_spriteColorizeM0_cbindings.s | 15 +- .../M0/cpct_spriteMaskedColorizeM0.asm | 48 +- .../cpct_spriteMaskedColorizeM0_asmbindings.s | 5 +- .../cpct_spriteMaskedColorizeM0_cbindings.s | 9 +- .../src/sprites/colorReplace/colorReplace.h | 15 +- examples/medium/colorReplace/src/drawing.c | 521 +++++++++--------- 20 files changed, 542 insertions(+), 606 deletions(-) delete mode 100644 cpctelera/src/sprites/colorReplace/M0/cpct_replaceColor.s delete mode 100644 cpctelera/src/sprites/colorReplace/M0/cpct_setReplaceColorsM0.asm delete mode 100644 cpctelera/src/sprites/colorReplace/M0/cpct_setReplaceColorsM0_cbinding.s diff --git a/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteColorizeM0.asm b/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteColorizeM0.asm index 9ee49f27e..a40ef9e87 100644 --- a/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteColorizeM0.asm +++ b/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteColorizeM0.asm @@ -25,13 +25,15 @@ ;; Directly replace a color and draw a sprite to video memory. ;; ;; C Definition: -;; void <cpct_drawSpriteColorizeM0> (void* *sprite*, void* *memory*, <u8> *width*, <u8> *height*) __z88dk_callee; +;; void <cpct_drawSpriteColorizeM0> (void* *sprite*, void* *memory*, <u8> *width*, <u8> *height*, <u8> *oldColor*, <u8> *newColor*) __z88dk_callee; ;; ;; Input Parameters (8 bytes): ;; (2B HL') sprite - Source Sprite Pointer (array of pixel data) ;; (2B DE') memory - Destination video memory pointer ;; (1B C' ) height - Sprite Height in bytes (>0) ;; (1B B' ) width - Sprite Width in *bytes* (Beware, *not* in pixels!) +;; (1B L ) oldColor - Color to replace +;; (1B H ) newColor - New color ;; ;; Assembly call (Input parameters on registers): ;; > call cpct_drawSpriteColorizeM0_asm @@ -52,6 +54,8 @@ ;; There is no practical upper limit to this value. Height of a sprite in ;; bytes and pixels is the same value, as bytes only group consecutive pixels in ;; the horizontal space. +;; * *oldColor* must be the index of color (0 to 15) to replace +;; * *newColor* must be the index of the new color (0 to 15) ;; ;; Known limitations: ;; * This function does not do any kind of boundary check or clipping. If you @@ -72,8 +76,8 @@ ;; AF, BC, DE, HL, BC', DE', HL', IX ;; ;; Required memory: -;; C-bindings - 165 bytes -;; ASM-bindings - 160 bytes +;; C-bindings - 118 bytes +;; ASM-bindings - 108 bytes ;; ;; Time Measures: ;; (start code) @@ -96,15 +100,32 @@ ;; Thanks to all of them for their help and support. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -.globl _cpct_color_old -.globl _cpct_color_new +.globl dc_mode0_ct - ;; newColor to pixel format (E) - ld a, (_cpct_color_new);; [4] A = mem new color index +;; Macro to convert Pixel to xAxC xBxD format +.macro convertPixel + ;; From cpct_px2byteM0 + ld bc, #dc_mode0_ct ;; [3] BC points to conversion table (dc_mode0_ct) + + ;; Compute BC += A + add c ;; [1] | C += A + ld c, a ;; [1] | + sub a ;; [1] A = 0 (preserving Carry Flag) + adc b ;; [1] | B += Carry + ld b, a ;; [1] | + + ;; A = *(BC + A) + ld a, (bc) ;; [2] A = Value stored at the table pointed by BC +.endm + + ;; Convert newColor to pixel format (E) + ld a, h ;; [1] A = H new color index + convertPixel ;; [10] | Convert into A ld e, a ;; [1] | E = A new color : xAxC xBxD - ;; oldColor to pixel format (D) - ld a, (_cpct_color_old);; [4] A = mem old color index + ;; Convert oldColor to pixel format (D) + ld a, l ;; [1] A = L old color index + convertPixel ;; [10] | Convert into A ld d, a ;; [1] | D = A old color : xAxC xBxD ld c, #0x55 ;; [2] C = Mask to get pixel A : xAxC xBxD @@ -126,7 +147,7 @@ lineLoop: and c ;; [2] A |= C (C = 0x55) : xBxB xBxB cp d ;; [1] Test if pixel (A) is the old colour to be replaced (D) - jr nz, readPixelA ;; [2/3] If not equal go to next pixel + jr nz, readPixelA ;; [2/3] If not equal go to next pixel ld a, e ;; [1] else A = new colour to set (E) ;; Pixel Mode 0 = ABAB ABAB diff --git a/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteColorizeM0_asmbindings.s b/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteColorizeM0_asmbindings.s index 01bfcad7c..073609b70 100644 --- a/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteColorizeM0_asmbindings.s +++ b/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteColorizeM0_asmbindings.s @@ -1,7 +1,7 @@ ;;-----------------------------LICENSE NOTICE------------------------------------ ;; This file is part of CPCtelera: An Amstrad CPC Game Engine -;; Copyright (C) 2018 Arnaud Bouche (@Arnaud6128) -;; Copyright (C) 2018 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) +;; Copyright (C) 2017 Arnaud Bouche (@Arnaud6128) +;; Copyright (C) 2017 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) ;; ;; This program is free software: you can redistribute it and/or modify ;; it under the terms of the GNU Lesser General Public License as published by @@ -18,7 +18,7 @@ ;;------------------------------------------------------------------------------- .module cpct_sprites -.include "../macros/cpct_undocumentedOpcodes.s" +.include "../../../macros/cpct_undocumentedOpcodes.h.s" ;; ;; ASM bindings for <cpct_drawSpriteColorizeM0> @@ -27,6 +27,7 @@ cpct_drawSpriteColorizeM0_asm:: ;; Assembly entry point ;; GET Parameters from the stack ld (dms_restore_ix + 2), ix ;; [6] Save IX to restore it before returning + pop hl ;; [3] HL = Return Address ;;.include /cpct_drawSpriteColorizeM0.asm/ diff --git a/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteColorizeM0_cbindings.s b/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteColorizeM0_cbindings.s index 9b8ed88e2..f4ad4b2f5 100644 --- a/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteColorizeM0_cbindings.s +++ b/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteColorizeM0_cbindings.s @@ -1,7 +1,7 @@ ;;-----------------------------LICENSE NOTICE------------------------------------ ;; This file is part of CPCtelera: An Amstrad CPC Game Engine -;; Copyright (C) 2018 Arnaud Bouche (@Arnaud6128) -;; Copyright (C) 2018 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) +;; Copyright (C) 2017 Arnaud Bouche (@Arnaud6128) +;; Copyright (C) 2017 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) ;; ;; This program is free software: you can redistribute it and/or modify ;; it under the terms of the GNU Lesser General Public License as published by @@ -18,18 +18,18 @@ ;;------------------------------------------------------------------------------- .module cpct_sprites -.include "../macros/cpct_undocumentedOpcodes.s" +.include "../../../macros/cpct_undocumentedOpcodes.h.s" ;; ;; C bindings for <cpct_drawSpriteColorizeM0> ;; -;; 33 us, 8 bytes +;; 33 us, 10 bytes ;; _cpct_drawSpriteColorizeM0:: ;; GET Parameters from the stack ld (dms_restore_ix + 2), ix ;; [6] Save IX to restore it before returning - pop de ;; [3] DE = Return Address + pop hl ;; [3] HL = Return Address exx pop hl ;; [3] HL' = Source address (Sprite) @@ -37,8 +37,9 @@ _cpct_drawSpriteColorizeM0:: pop bc ;; [5] BC' = (B = Sprite Height, C = Width) exx - push de ;; [4] Put returning address in the stack again - ;; as this function uses __z88dk_callee convention + ex (sp), hl ;; [6] HL = (H = newColor, L = oldColor) + ;; ... and leave Return Address at (SP) as we don't need to restore + ;; ... stack status because callin convention is __z88dk_callee .include /cpct_drawSpriteColorizeM0.asm/ diff --git a/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteMaskedAlignedColorizeM0.asm b/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteMaskedAlignedColorizeM0.asm index a0dda77a4..981c21ab2 100644 --- a/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteMaskedAlignedColorizeM0.asm +++ b/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteMaskedAlignedColorizeM0.asm @@ -18,6 +18,8 @@ ;;------------------------------------------------------------------------------- .module cpct_sprites +.globl dc_mode0_ct + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; Function: cpct_drawSpriteMaskedAlignedColorizeM0 @@ -26,13 +28,15 @@ ;; ;; C Definition: ;; void <cpct_drawSpriteMaskedAlignedColorizeM0> (void* *sprite*, void* *memory*, <u8> *width*, <u8> *height*, -;; <u8*> *pmasktable*) __z88dk_callee; +;; <u8> *oldColor*, <u8> *newColor*, <u8*> *pmasktable*) __z88dk_callee; ;; -;; Input Parameters (8 bytes): +;; Input Parameters (10 bytes): ;; (2B HL') sprite - Source Sprite Pointer (array of pixel data) ;; (2B DE') memory - Destination video memory pointer ;; (1B C' ) height - Sprite Height in bytes (>0) ;; (1B B' ) width - Sprite Width in *bytes* (Beware, *not* in pixels!) +;; (1B E ) oldColor - Color to replace +;; (1B D ) newColor - New color ;; (2B HL) pmasktable - Pointer to the aligned mask table used to create transparency ;; ;; Assembly call (Input parameters on registers): @@ -54,6 +58,8 @@ ;; There is no practical upper limit to this value. Height of a sprite in ;; bytes and pixels is the same value, as bytes only group consecutive pixels in ;; the horizontal space. +;; * *oldColor* must be the index of color (0 to 15) to replace +;; * *newColor* must be the index of the new color (0 to 15) ;; ;; Known limitations: ;; * This function does not do any kind of boundary check or clipping. If you @@ -74,8 +80,8 @@ ;; AF, BC, DE, HL, BC', DE', HL', IX ;; ;; Required memory: -;; C-bindings - 165 bytes -;; ASM-bindings - 160 bytes +;; C-bindings - 112 bytes +;; ASM-bindings - 96 bytes ;; ;; Time Measures: ;; (start code) @@ -98,82 +104,97 @@ ;; Thanks to all of them for their help and support. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -.globl _cpct_color_old -.globl _cpct_color_new +;; Macro to convert Pixel to xAxC xBxD format +.macro convertPixel + ;; From cpct_px2byteM0 + ld bc, #dc_mode0_ct ;; [3] BC points to conversion table (dc_mode0_ct) + + ;; Compute BC += A + add c ;; [1] | C += A + ld c, a ;; [1] | + sub a ;; [1] A = 0 (preserving Carry Flag) + adc b ;; [1] | B += Carry + ld b, a ;; [1] | + + ;; A = *(BC + A) + ld a, (bc) ;; [2] A = Value stored at the table pointed by BC +.endm - ;; newColor to pixel format (E) - ld a, (_cpct_color_new);; [4] A = mem new color index + ;; Convert newColor to pixel format (E) + ld a, h ;; [1] A = H new color index + convertPixel ;; [10] | Convert into A ld e, a ;; [1] | E = A new color : xAxC xBxD - ;; oldColor to pixel format (D) - ld a, (_cpct_color_old);; [4] A = mem old color index - ld b, d ;; [1] B = D (Masked table adress High Byte) - ld d, a ;; [1] | D = A old color : xAxC xBxD - - ld c, #0x55 ;; [2] C = Mask to get pixel A : xAxC xBxD - exx ;; [1] Switch to Alternate registers - - ld__ixl_c ;; [1] IXL = C (Width) - ld c, b ;; [1] C = B (Height) - -convertLoop: - push de ;; [4] Store DE start line (DestMem) - ld__b_ixl ;; [2] B = IXL (Sprite Width) + ;; Convert oldColor to pixel format (D) + ld a, l ;; [1] A = L old color index + convertPixel ;; [10] | Convert into A + ld b, d + ld d, a ;; [1] | D = A old color : xAxC xBxD + + ld c, #0x55 ;; [2] C = Mask to get pixel A : xAxC xBxD + exx ;; [1] Switch to Alternate registers + + ld__ixl_c ;; [1] IXL = C (Width) + ld c, b ;; [1] C = B (Height) + +convertLoop: + push de ;; [4] Store DE start line (DestMem) + ld__b_ixl ;; [2] B = IXL (Sprite Width) lineLoop: - ld a, (hl) ;; [2] A = (HL) current Byte of sprite + ld a, (hl) ;; [2] A = (HL) current Byte of sprite exx ;; [1] Switch to Default registers - - ld l, a ;; [1] L = A current Byte of sprite : ABAB ABAB - and c ;; [2] A |= C (C = 0x55) : xBxB xBxB - - cp d ;; [1] Test if pixel (A) is the old colour to be replaced (D) - jr nz, readPixelA ;; [2/3] If not equal go to next pixel + + ld l, a ;; [1] L = A current Byte of sprite : ABAB ABAB + and c ;; [2] A |= C (C = 0x55) : xBxB xBxB + + cp d ;; [1] Test if pixel (A) is the old colour to be replaced (D) + jr nz, readPixelA ;; [2/3] If not equal go to next pixel ld a, e ;; [1] else A = new colour to set (E) ;; Pixel Mode 0 = ABAB ABAB readPixelA: - ld h, a ;; [1] H = A (current colorized sprite) : xBxB xBxB - ld a, l ;; [1] L = A current Byte of sprite : ABAB ABAB - rrca ;; [1] A (current byte of sprite) >> 1 : ABAB ABAB -> xABA BABA - and c ;; [2] A |= Mask (0x55) : xAxA xAxA - - cp d ;; [1] Test if pixel (A) is the old colour to be replaced (D) - jr nz, readPixelB ;; [2/3] If not equal go to next pixel + ld h, a ;; [1] H = A (current colorized sprite) : xBxB xBxB + ld a, l ;; [1] L = A current Byte of sprite : ABAB ABAB + rrca ;; [1] A (current byte of sprite) >> 1 : ABAB ABAB -> xABA BABA + and c ;; [2] A |= Mask (0x55) : xAxA xAxA + + cp d ;; [1] Test if pixel (A) is the old colour to be replaced (D) + jr nz, readPixelB ;; [2/3] If not equal go to next pixel ld a, e ;; [1] else A = new colour to set (E) - + readPixelB: - rlca ;; [1] A = xAxA xAxA << 1 : AxAx AxAx - or h ;; [1] A |= H (xBxB xBxB) : ABAB ABAB + rlca ;; [1] A = xAxA xAxA << 1 : AxAx AxAx + or h ;; [1] A |= H (xBxB xBxB) : ABAB ABAB drawByte: ld h, b ;; [1] H = B (Masked table adress High Byte) - ld l, a ;; [1] Access mask table element (table must be 256-byte aligned) - exx ;; [1] Switch to Alternate registers - - ld a, (de) ;; [2] Get the value of the byte of the screen where we are going to draw - exx ;; [1] Switch to Default registers - - and (hl) ;; [2] Erase background part that is to be overwritten (Mask step 1) - or l ;; [1] Add up background and sprite information in one byte (Mask step 2) - exx ;; [1] Switch to Alternate registers - - ld (de), a ;; [2] Save modified background + sprite data information into memory + ld l, a ;; [1] Access mask table element (table must be 256-byte aligned) + exx ;; [1] Switch to Alternate registers + + ld a, (de) ;; [2] Get the value of the byte of the screen where we are going to draw + exx ;; [1] Switch to Default registers + + and (hl) ;; [2] Erase background part that is to be overwritten (Mask step 1) + or l ;; [1] Add up background and sprite information in one byte (Mask step 2) + exx ;; [1] Switch to Alternate registers + + ld (de), a ;; [2] Save modified background + sprite data information into memory - inc hl ;; [2] Next byte sprite source - inc de ;; [2] Next byte sprite colorized - djnz lineLoop ;; [3] Decrement B (Width) if B != 0 goto lineLoop - - dec c ;; [1] Decrement C (Height) - jr z, end ;; [2/3] If C == O goto end + inc hl ;; [2] Next byte sprite source + inc de ;; [2] Next byte sprite colorized + djnz lineLoop ;; [3] Decrement B (Width) if B != 0 goto lineLoop + + dec c ;; [1] Decrement C (Height) + jr z, end ;; [2/3] If C == O goto end - pop de ;; [3] Restore DE start line (DestMem) + pop de ;; [3] Restore DE start line (DestMem) ld a, d ;; [1] Start of next pixel line normally is 0x0800 bytes away. add #0x08 ;; [2] so we add it to DE (just by adding 0x08 to D) ld d, a ;; [1] - and #0x38 ;; [2] We check if we have crossed memory boundary (every 8 pixel lines).. - + and #0x38 ;; [2] We check if we have crossed memory boundary (every 8 pixel lines).. + jr nz, convertLoop ;; [2/3] .. by checking the 4 bits that identify present memory line. ;; .... If 0, we have crossed boundaries @@ -184,11 +205,11 @@ dms_sprite_8bit_boundary_crossed: ld a, d ;; [1] -- which effectively is the same as moving it 1 bank backwards and then adc #0xC0 ;; [2] -- 50 bytes forwards (which is what we want to move it to the next pixel line) ld d, a ;; [1] -- Calculations are made with 8 bit maths as it is faster than other alternatives here - - jr convertLoop ;; [3] Jump to continue with next pixel line + + jr convertLoop ;; [3] Jump to continue with next pixel line end: pop de ;; [3] Empty stack by getting last element (DestMem) - ;; Return is included in bindings - - + ;; Return is included in bindings + + diff --git a/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteMaskedAlignedColorizeM0_asmbindings.s b/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteMaskedAlignedColorizeM0_asmbindings.s index 868def72a..f566e8fc5 100644 --- a/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteMaskedAlignedColorizeM0_asmbindings.s +++ b/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteMaskedAlignedColorizeM0_asmbindings.s @@ -1,7 +1,7 @@ ;;-----------------------------LICENSE NOTICE------------------------------------ ;; This file is part of CPCtelera: An Amstrad CPC Game Engine -;; Copyright (C) 2018 Arnaud Bouche (@Arnaud6128) -;; Copyright (C) 2018 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) +;; Copyright (C) 2017 Arnaud Bouche (@Arnaud6128) +;; Copyright (C) 2017 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) ;; ;; This program is free software: you can redistribute it and/or modify ;; it under the terms of the GNU Lesser General Public License as published by @@ -18,7 +18,7 @@ ;;------------------------------------------------------------------------------- .module cpct_sprites -.include "../macros/cpct_undocumentedOpcodes.s" +.include "../../../macros/cpct_undocumentedOpcodes.h.s" ;; ;; ASM bindings for <cpct_drawSpriteMaskedAlignedColorizeM0> @@ -27,6 +27,7 @@ cpct_drawSpriteMaskedAlignedColorizeM0_asm:: ;; Assembly entry point ;; GET Parameters from the stack ld (dms_restore_ix + 2), ix ;; [6] Save IX to restore it before returning + pop hl ;; [3] HL = Return Address .include /cpct_drawSpriteMaskedAlignedColorizeM0.asm/ diff --git a/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteMaskedAlignedColorizeM0_cbindings.s b/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteMaskedAlignedColorizeM0_cbindings.s index 01d9eee57..f8953c60b 100644 --- a/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteMaskedAlignedColorizeM0_cbindings.s +++ b/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteMaskedAlignedColorizeM0_cbindings.s @@ -1,7 +1,7 @@ ;;-----------------------------LICENSE NOTICE------------------------------------ ;; This file is part of CPCtelera: An Amstrad CPC Game Engine -;; Copyright (C) 2018 Arnaud Bouche (@Arnaud6128) -;; Copyright (C) 2018 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) +;; Copyright (C) 2017 Arnaud Bouche (Arnaud6128) +;; Copyright (C) 2017 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) ;; ;; This program is free software: you can redistribute it and/or modify ;; it under the terms of the GNU Lesser General Public License as published by @@ -18,12 +18,12 @@ ;;------------------------------------------------------------------------------- .module cpct_sprites -.include "../macros/cpct_undocumentedOpcodes.s" +.include "../../../macros/cpct_undocumentedOpcodes.h.s" ;; ;; C bindings for <cpct_drawSpriteMaskedAlignedColorizeM0> ;; -;; 39 us, 8 bytes +;; 39 us, 16 bytes ;; _cpct_drawSpriteMaskedAlignedColorizeM0:: @@ -37,10 +37,13 @@ _cpct_drawSpriteMaskedAlignedColorizeM0:: pop bc ;; [5] BC' = (B = Sprite Height, C = Width) exx ;; [1] Switch to Default registers - pop de ;; [3] DE = Table Mask address + pop de ;; [3] DE = (D = newColor, E = oldColor) - push hl ;; [4] Put returning address in the stack again - ;; as this function uses __z88dk_callee convention + ex (sp), hl ;; [6] HL = Table Mask address + ;; ... and leave Return Address at (SP) as we don't need to restore + ;; ... stack status because callin convention is __z88dk_callee + + ex de, hl ;; [1] HL <-> DE .include /cpct_drawSpriteMaskedAlignedColorizeM0.asm/ diff --git a/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteMaskedColorizeM0.asm b/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteMaskedColorizeM0.asm index 7862cdaeb..8f63f4c99 100644 --- a/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteMaskedColorizeM0.asm +++ b/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteMaskedColorizeM0.asm @@ -1,7 +1,7 @@ ;;-----------------------------LICENSE NOTICE------------------------------------ ;; This file is part of CPCtelera: An Amstrad CPC Game Engine -;; Copyright (C) 2018 Arnaud Bouche (@Arnaud6128) -;; Copyright (C) 2018 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) +;; Copyright (C) 2017 Arnaud Bouche +;; Copyright (C) 2017 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) ;; ;; This program is free software: you can redistribute it and/or modify ;; it under the terms of the GNU Lesser General Public License as published by @@ -18,6 +18,8 @@ ;;------------------------------------------------------------------------------- .module cpct_sprites +.globl dc_mode0_ct + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; Function: cpct_drawSpriteMaskedColorizeM0 @@ -25,13 +27,15 @@ ;; Directly replace a color and draw a sprite Masked to video memory. ;; ;; C Definition: -;; void <cpct_drawSpriteMaskedColorizeM0> (void* *sprite*, void* *memory*, <u8> *width*, <u8> *height*) __z88dk_callee; +;; void <cpct_drawSpriteMaskedColorizeM0> (void* *sprite*, void* *memory*, <u8> *width*, <u8> *height*, <u8> *oldColor*, <u8> *newColor*) __z88dk_callee; ;; -;; Input Parameters (6 bytes): +;; Input Parameters (8 bytes): ;; (2B HL') sprite - Source Sprite Pointer (array of pixel data) ;; (2B DE') memory - Destination video memory pointer ;; (1B C' ) height - Sprite Height in bytes (>0) ;; (1B B' ) width - Sprite Width in *bytes* (Beware, *not* in pixels!) +;; (1B L ) oldColor - Color to replace +;; (1B H ) newColor - New color ;; ;; Assembly call (Input parameters on registers): ;; > call cpct_drawSpriteMaskedColorizeM0_asm @@ -57,6 +61,8 @@ ;; There is no practical upper limit to this value. Height of a sprite in ;; bytes and pixels is the same value, as bytes only group consecutive pixels in ;; the horizontal space. +;; * *oldColor* must be the index of color (0 to 15) to replace +;; * *newColor* must be the index of the new color (0 to 15) ;; ;; Known limitations: ;; * This function does not do any kind of boundary check or clipping. If you @@ -74,21 +80,20 @@ ;; * This function requires the CPC firmware to be DISABLED. Otherwise, random crashes might happen due to side effects. ;; ;; Destroyed Register values: -;; AF, BC, DE, BC', DE', HL', IX +;; AF, BC, DE, HL, BC', DE', HL', IX ;; ;; Required memory: -;; C-bindings - 165 bytes -;; ASM-bindings - 160 bytes +;; C-bindings - 115 bytes +;; ASM-bindings - 102 bytes ;; ;; Time Measures: ;; (start code) ;; Case | microSecs (us) | CPU Cycles ;; ---------------------------------------------------------------- -;; Best | | -;; Worst | | +;; Best | 29 + (50 + 36W)H | 116 + (200 + 144W)H ;; ---------------------------------------------------------------- -;; W=2,H=16 | | -;; W=4,H=32 | | +;; W=2,H=16 | 1981 | 7924 +;; W=4,H=32 | 6237 | 24948 ;; ---------------------------------------------------------------- ;; Asm saving | -16 | -64 ;; ---------------------------------------------------------------- @@ -102,21 +107,34 @@ ;; Thanks to all of them for their help and support. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -.globl _cpct_color_old -.globl _cpct_color_new +;; Macro to convert Pixel to xAxC xBxD format +.macro convertPixel + ;; From cpct_px2byteM0 + ld bc, #dc_mode0_ct ;; [3] BC points to conversion table (dc_mode0_ct) + + ;; Compute BC += A + add c ;; [1] | C += A + ld c, a ;; [1] | + sub a ;; [1] A = 0 (preserving Carry Flag) + adc b ;; [1] | B += Carry + ld b, a ;; [1] | + + ;; A = *(BC + A) + ld a, (bc) ;; [2] A = Value stored at the table pointed by BC +.endm - ;; newColor to pixel format (E) - ld a, (_cpct_color_new);; [4] A = mem new color index + ;; Convert newColor to pixel format (E) + ld a, h ;; [1] A = H new color index + convertPixel ;; [10] | Convert into A ld e, a ;; [1] | E = A new color : xAxC xBxD - ;; oldColor to pixel format (D) - ld a, (_cpct_color_old);; [4] A = mem old color index + ;; Convert oldColor to pixel format (D) + ld a, l ;; [1] A = L old color index + convertPixel ;; [10] | Convert into A ld d, a ;; [1] | D = A old color : xAxC xBxD ld c, #0x55 ;; [2] C = Mask to get pixel A : xAxC xBxD - ld c, #0x55 ;; [2] C = Mask to get pixel A : xAxC xBxD - exx ;; [1] Switch to Alternate registers ld__ixl_c ;; [1] IXL = C (Width) diff --git a/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteMaskedColorizeM0_asmbindings.s b/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteMaskedColorizeM0_asmbindings.s index a8806e008..48bc1ef3c 100644 --- a/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteMaskedColorizeM0_asmbindings.s +++ b/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteMaskedColorizeM0_asmbindings.s @@ -18,7 +18,7 @@ ;;------------------------------------------------------------------------------- .module cpct_sprites -.include "../macros/cpct_undocumentedOpcodes.s" +.include "../../../macros/cpct_undocumentedOpcodes.h.s" ;; ;; ASM bindings for <cpct_drawSpriteMaskedColorizeM0> @@ -27,6 +27,7 @@ cpct_drawSpriteMaskedColorizeM0_asm:: ;; Assembly entry point ;; GET Parameters from the stack ld (dms_restore_ix + 2), ix ;; [6] Save IX to restore it before returning + pop hl ;; [3] HL = Return Address .include /cpct_drawSpriteMaskedColorizeM0.asm/ diff --git a/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteMaskedColorizeM0_cbindings.s b/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteMaskedColorizeM0_cbindings.s index 1f0fd6e66..18f336eb5 100644 --- a/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteMaskedColorizeM0_cbindings.s +++ b/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteMaskedColorizeM0_cbindings.s @@ -18,18 +18,18 @@ ;;------------------------------------------------------------------------------- .module cpct_sprites -.include "../macros/cpct_undocumentedOpcodes.s" +.include "../../../macros/cpct_undocumentedOpcodes.h.s" ;; ;; C bindings for <cpct_drawSpriteMaskedColorizeM0> ;; -;; 33 us, 8 bytes +;; 33 us, 13 bytes ;; _cpct_drawSpriteMaskedColorizeM0:: ;; GET Parameters from the stack ld (dms_restore_ix + 2), ix ;; [6] Save IX to restore it before returning - pop de ;; [3] DE = Return Address + pop hl ;; [3] HL = Return Address exx pop hl ;; [3] HL' = Source address (Sprite) @@ -37,8 +37,9 @@ _cpct_drawSpriteMaskedColorizeM0:: pop bc ;; [5] BC' = (B = Sprite Height, C = Width) exx - push de ;; [4] Put returning address in the stack again - ;; as this function uses __z88dk_callee convention + ex (sp), hl ;; [6] HL = (H = newColor, L = oldColor) + ;; ... and leave Return Address at (SP) as we don't need to restore + ;; ... stack status because callin convention is __z88dk_callee .include /cpct_drawSpriteMaskedColorizeM0.asm/ diff --git a/cpctelera/src/sprites/colorReplace/M0/cpct_replaceColor.s b/cpctelera/src/sprites/colorReplace/M0/cpct_replaceColor.s deleted file mode 100644 index 260c2ea15..000000000 --- a/cpctelera/src/sprites/colorReplace/M0/cpct_replaceColor.s +++ /dev/null @@ -1,44 +0,0 @@ -;;-----------------------------LICENSE NOTICE------------------------------------ -;; This file is part of CPCtelera: An Amstrad CPC Game Engine -;; Copyright (C) 2018 Arnaud Bouche (@Arnaud6128) -;; Copyright (C) 2018 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) -;; -;; This program is free software: you can redistribute it and/or modify -;; it under the terms of the GNU Lesser General Public License as published by -;; the Free Software Foundation, either version 3 of the License, or -;; (at your option) any later version. -;; -;; This program is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU Lesser General Public License for more details. -;; -;; You should have received a copy of the GNU Lesser General Public License -;; along with this program. If not, see <http://www.gnu.org/licenses/>. -;;------------------------------------------------------------------------------- -.module cpct_sprites - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; -;; Variables: cpct_color_old, cpct_color_new -;; -;; Contains the colors to be used by theses functions: -;; * cpct_setReplaceColors -;; * cpct_spriteColorizeM0 -;; * cpct_spriteColorizeM1 -;; * cpct_drawSpriteColorizeM0 -;; * cpct_drawSpriteColorizeM1 -;; -;; C Definition: -;; <u8> <cpct_color_old>; -;; <u8> <cpct_color_new>; -;; -;; Known limitations: -;; * These color are used for Mode0 (0 to 15) and Mode1 (0 to 3) -;; * You may assing a value to this seed direcly from C or ASM. If directly accessed -;; from ASM, do not forget to put an underscore in front (_cpct_color_old and _cpct_color_new). -;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -_cpct_color_old:: .db #00 -_cpct_color_new:: .db #00 \ No newline at end of file diff --git a/cpctelera/src/sprites/colorReplace/M0/cpct_setReplaceColorsM0.asm b/cpctelera/src/sprites/colorReplace/M0/cpct_setReplaceColorsM0.asm deleted file mode 100644 index 47c9308a7..000000000 --- a/cpctelera/src/sprites/colorReplace/M0/cpct_setReplaceColorsM0.asm +++ /dev/null @@ -1,87 +0,0 @@ -;;-----------------------------LICENSE NOTICE------------------------------------ -;; This file is part of CPCtelera: An Amstrad CPC Game Engine -;; Copyright (C) 2018 Arnaud Bouche (@Arnaud6128) -;; Copyright (C) 2018 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) -;; -;; This program is free software: you can redistribute it and/or modify -;; it under the terms of the GNU Lesser General Public License as published by -;; the Free Software Foundation, either version 3 of the License, or -;; (at your option) any later version. -;; -;; This program is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU Lesser General Public License for more details. -;; -;; You should have received a copy of the GNU Lesser General Public License -;; along with this program. If not, see <http://www.gnu.org/licenses/>. -;;------------------------------------------------------------------------------- -.module cpct_sprites - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; -;; Function: cpct_setReplaceColorsM0 -;; -;; Sets the colors to be used with the replace colors for Mode 0 functions -;; -;; C Definition: -;; void <cpct_setReplaceColorsM0> (<u8> *oldColor*, <u8> *newColor*) __z88dk_fastcall; -;; -;; Input Parameters (2 bytes): -;; (1B D) *oldColor* - Color to be replaced. -;; (1B E) *newColor* - Color to set. -;; -;; Assembly call: -;; > call cpct_setReplaceColorsM0 -;; -;; Parameter Restrictions: -;; * There is not check on the color value according to the Mode 0 (0 to 15) -;; -;; Destroyed Register values: -;; A, BC, DE -;; -;; Required memory: -;; 8 bytes -;; -;; Time Measures: -;; (start code) -;; Case | microSecs (us) | CPU Cycles -;; ----------------------------------------- -;; Any | 14 | 56 -;; ----------------------------------------- -;; (end code) -;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -.globl dc_mode0_ct - -;; Macro to convert Pixel to xAxC xBxD format -.macro convertPixel - ;; From cpct_px2byteM0 - ld bc, #dc_mode0_ct ;; [3] BC points to conversion table (dc_mode0_ct) - - ;; Compute BC += A - add c ;; [1] | C += A - ld c, a ;; [1] | - sub a ;; [1] A = 0 (preserving Carry Flag) - adc b ;; [1] | B += Carry - ld b, a ;; [1] | - - ;; A = *(BC + A) - ld a, (bc) ;; [2] A = Value stored at the table pointed by BC -.endm - -.globl _cpct_color_old -.globl _cpct_color_new - - ;; Convert New color - ld a, h ;; [1] A = H new color - convertPixel ;; [10] | Convert into A - ld (_cpct_color_new), a ;; [3] | store color in memory - - ;; Convert Old color - ld a, l ;; [1] A = L old color - convertPixel ;; [10] | Convert into A - ld (_cpct_color_old), a ;; [3] | store color in memory - - ret ;; [3] \ No newline at end of file diff --git a/cpctelera/src/sprites/colorReplace/M0/cpct_setReplaceColorsM0_cbinding.s b/cpctelera/src/sprites/colorReplace/M0/cpct_setReplaceColorsM0_cbinding.s deleted file mode 100644 index 5792fed64..000000000 --- a/cpctelera/src/sprites/colorReplace/M0/cpct_setReplaceColorsM0_cbinding.s +++ /dev/null @@ -1,31 +0,0 @@ -;;-----------------------------LICENSE NOTICE------------------------------------ -;; This file is part of CPCtelera: An Amstrad CPC Game Engine -;; Copyright (C) 2018 Arnaud Bouche (@Arnaud6128) -;; Copyright (C) 2018 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) -;; -;; This program is free software: you can redistribute it and/or modify -;; it under the terms of the GNU Lesser General Public License as published by -;; the Free Software Foundation, either version 3 of the License, or -;; (at your option) any later version. -;; -;; This program is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU Lesser General Public License for more details. -;; -;; You should have received a copy of the GNU Lesser General Public License -;; along with this program. If not, see <http://www.gnu.org/licenses/>. -;;------------------------------------------------------------------------------- -.module cpct_sprites - -;; -;; C bindings for <cpct_px2byteM0> -;; -;; 9 us, 2 bytes -;; -_cpct_setReplaceColorsM0:: - ;; Recover parameters from the stack - pop hl ;; [3] HL = Return Address - ex (sp), hl ;; [6] HL => L : Old Color, H : New Color - -.include /cpct_setReplaceColorsM0.asm/ \ No newline at end of file diff --git a/cpctelera/src/sprites/colorReplace/M0/cpct_spriteColorizeM0.asm b/cpctelera/src/sprites/colorReplace/M0/cpct_spriteColorizeM0.asm index a6d9090c0..f319db09c 100644 --- a/cpctelera/src/sprites/colorReplace/M0/cpct_spriteColorizeM0.asm +++ b/cpctelera/src/sprites/colorReplace/M0/cpct_spriteColorizeM0.asm @@ -25,13 +25,15 @@ ;; Replace a color in a sprite and copy to another or the same sprite. ;; ;; C Definition: -;; void <cpct_spriteColorizeM0> (void* *sprite*, void* *spriteColor*, <u8> *width*, <u8> *height*) __z88dk_callee; +;; void <cpct_spriteColorizeM0> (void* *sprite*, void* *spriteColor*, <u8> *width*, <u8> *height*, <u8> *oldColor*, <u8> *newColor*) __z88dk_callee; ;; ;; Input Parameters (6 bytes): ;; (2B HL') sprite - Source Sprite Pointer (array of pixel data) ;; (2B DE') spriteColor - Destination Sprite Pointer (can be also the Source Sprite) (array of pixel data) ;; (1B C' ) height - Sprite Height in bytes (>0) ;; (1B B' ) width - Sprite Width in *bytes* (Beware, *not* in pixels!) +;; (1B L ) oldColor - Color to replace +;; (1B H ) newColor - New color ;; ;; Assembly call (Input parameters on registers): ;; > call cpct_spriteColorizeM0_asm @@ -49,31 +51,33 @@ ;; There is no practical upper limit to this value. Height of a sprite in ;; bytes and pixels is the same value, as bytes only group consecutive pixels in ;; the horizontal space. +;; * *oldColor* must be the index of color (0 to 15) to replace +;; * *newColor* must be the index of the new color (0 to 15) ;; ;; Known limitations: ;; * This function *will not work from ROM*, as it uses self-modifying code. ;; * This function requires the CPC firmware to be DISABLED. Otherwise, random crashes might happen due to side effects. ;; ;; Destroyed Register values: -;; AF, BC, DE, BC', DE', HL', IX +;; AF, BC, DE, HL, BC', DE', HL', IX ;; ;; Required memory: -;; C-bindings - 165 bytes -;; ASM-bindings - 160 bytes +;; C-bindings - 81 bytes +;; ASM-bindings - 67 bytes ;; ;; Time Measures: ;; (start code) ;; Case | microSecs (us) | CPU Cycles ;; ---------------------------------------------------------------- -;; | 29 + (33 + 4W)H | 116 + (132 + 16W)H +;; | 29 + (6 + 33W)H | 116 + (24 + 132W)H ;; ---------------------------------------------------------------- -;; W=2,H=16 | 685 | 2740 -;; W=4,H=32 | 1597 | 6388 +;; W=2,H=16 | 1181 | 4724 +;; W=4,H=32 | 4445 | 17780 ;; ---------------------------------------------------------------- ;; Asm saving | -16 | -64 ;; ---------------------------------------------------------------- ;; (end code) -;; W = *width* in bytes, H = *height* in bytes, HH = [(H-1)/8] +;; W = *width* in bytes, H = *height* in bytes ;; ;; Credits: ;; Original routine optimized by @Docent and discussed in CPCWiki : @@ -82,19 +86,35 @@ ;; Thanks to all of them for their help and support. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -.globl _cpct_color_old -.globl _cpct_color_new +.globl dc_mode0_ct - ;; newColor to pixel format (E) - ld a, (_cpct_color_new);; [4] A = mem new color index +;; Macro to convert Pixel to xAxC xBxD format +.macro convertPixel + ;; From cpct_px2byteM0 + ld bc, #dc_mode0_ct ;; [3] BC points to conversion table (dc_mode0_ct) + + ;; Compute BC += A + add c ;; [1] | C += A + ld c, a ;; [1] | + sub a ;; [1] A = 0 (preserving Carry Flag) + adc b ;; [1] | B += Carry + ld b, a ;; [1] | + + ;; A = *(BC + A) + ld a, (bc) ;; [2] A = Value stored at the table pointed by BC +.endm + + ;; Convert newColor to pixel format (E) + ld a, h ;; [1] A = H new color index + convertPixel ;; [10] | Convert into A ld e, a ;; [1] | E = A new color : xAxC xBxD - ;; oldColor to pixel format (D) - ld a, (_cpct_color_old);; [4] A = mem old color index + ;; Convert oldColor to pixel format (D) + ld a, l ;; [1] A = L old color index + convertPixel ;; [10] | Convert into A ld d, a ;; [1] | D = A old color : xAxC xBxD ld c, #0x55 ;; [2] C = Mask to get pixel A : xAxC xBxD - exx ;; [1] Switch to Alternate registers ld__ixl_c ;; [1] IXL = C (Width) @@ -104,7 +124,7 @@ convertLoop: ld__b_ixl ;; [2] B = IXL (Sprite Width) lineLoop: - ld a, (hl) ;; [2] A = (HL') current Byte of sprite + ld a, (hl) ;; [2] A = (HL) current Byte of sprite exx ;; [1] Switch to Default registers ld l, a ;; [1] L = A current Byte of sprite : ABAB ABAB @@ -139,7 +159,8 @@ setByte: nextLine: dec c ;; [1] Decrement C (Height) - jr nz, convertLoop ;; [1] If != O goto convertLoop + jr nz, convertLoop ;; [2/3] If != O goto convertLoop end: - ;; Return is included in bindings \ No newline at end of file + ;; Return is included in bindings + diff --git a/cpctelera/src/sprites/colorReplace/M0/cpct_spriteColorizeM0_asmbindings.s b/cpctelera/src/sprites/colorReplace/M0/cpct_spriteColorizeM0_asmbindings.s index 1362dbb6b..3339b8ea5 100644 --- a/cpctelera/src/sprites/colorReplace/M0/cpct_spriteColorizeM0_asmbindings.s +++ b/cpctelera/src/sprites/colorReplace/M0/cpct_spriteColorizeM0_asmbindings.s @@ -18,19 +18,19 @@ ;;------------------------------------------------------------------------------- .module cpct_sprites -.include "../macros/cpct_undocumentedOpcodes.s" +.include "../../../macros/cpct_undocumentedOpcodes.h.s" ;; ;; ASM bindings for <cpct_spriteColorizeM0> ;; cpct_spriteColorizeM0_asm:: ;; Assembly entry point - ;; GET Parameters from the stack - ld (dms_restore_ix + 2), ix ;; [6] Save IX to restore it before returning + ;; GET Parameters from the stack + ld (dms_restore_ix + 2), ix ;; [6] Save IX to restore it before returning + pop hl ;; [3] HL = Return Address .include /cpct_spriteColorizeM0.asm/ dms_restore_ix: ld ix, #0000 ;; [4] Restore IX before returning - ret ;; [3] Return to caller - + ret ;; [3] Return to caller \ No newline at end of file diff --git a/cpctelera/src/sprites/colorReplace/M0/cpct_spriteColorizeM0_cbindings.s b/cpctelera/src/sprites/colorReplace/M0/cpct_spriteColorizeM0_cbindings.s index 4d67122d8..27d164918 100644 --- a/cpctelera/src/sprites/colorReplace/M0/cpct_spriteColorizeM0_cbindings.s +++ b/cpctelera/src/sprites/colorReplace/M0/cpct_spriteColorizeM0_cbindings.s @@ -18,7 +18,7 @@ ;;------------------------------------------------------------------------------- .module cpct_sprites -.include "../macros/cpct_undocumentedOpcodes.s" +.include "../../../macros/cpct_undocumentedOpcodes.h.s" ;; ;; C bindings for <cpct_spriteColorizeM0> @@ -29,19 +29,20 @@ _cpct_spriteColorizeM0:: ;; GET Parameters from the stack ld (dms_restore_ix + 2), ix ;; [6] Save IX to restore it before returning - pop de ;; [3] DE = Return Address + pop hl ;; [3] HL = Return Address - exx ;; [1] Swap to alternate registers + exx pop hl ;; [3] HL' = Source address (Sprite) pop de ;; [3] DE' = Destination Sprite color pop bc ;; [5] BC' = (B = Sprite Height, C = Width) - exx ;; [1] Swap to default registers + exx - push de ;; [4] Put returning address in the stack again - ;; as this function uses __z88dk_callee convention + ex (sp), hl ;; [6] HL = (H = newColor, L = oldColor) + ;; ... and leave Return Address at (SP) as we don't need to restore + ;; ... stack status because callin convention is __z88dk_callee .include /cpct_spriteColorizeM0.asm/ dms_restore_ix: ld ix, #0000 ;; [4] Restore IX before returning - ret ;; [3] Return to caller + ret ;; [3] Return to caller \ No newline at end of file diff --git a/cpctelera/src/sprites/colorReplace/M0/cpct_spriteMaskedColorizeM0.asm b/cpctelera/src/sprites/colorReplace/M0/cpct_spriteMaskedColorizeM0.asm index 6ebf9798b..37a32f02e 100644 --- a/cpctelera/src/sprites/colorReplace/M0/cpct_spriteMaskedColorizeM0.asm +++ b/cpctelera/src/sprites/colorReplace/M0/cpct_spriteMaskedColorizeM0.asm @@ -1,6 +1,6 @@ ;;-----------------------------LICENSE NOTICE------------------------------------ ;; This file is part of CPCtelera: An Amstrad CPC Game Engine -;; Copyright (C) 2018 Arnaud Bouche (@Arnaud6128)) +;; Copyright (C) 2018 Arnaud Bouche (@Arnaud6128) ;; Copyright (C) 2018 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) ;; ;; This program is free software: you can redistribute it and/or modify @@ -25,13 +25,15 @@ ;; Replace a color in a Masked sprite and copy to another or the same sprite. ;; ;; C Definition: -;; void <cpct_spriteMaskedColorizeM0> (void* *sprite*, void* *spriteColor*, <u8> *width*, <u8> *height*) __z88dk_callee; +;; void <cpct_spriteMaskedColorizeM0> (void* *sprite*, void* *spriteColor*, <u8> *width*, <u8> *height*, <u8> *oldColor*, <u8> *newColor*) __z88dk_callee; ;; ;; Input Parameters (6 bytes): ;; (2B HL') sprite - Source Sprite Pointer (array of pixel data) ;; (2B DE') spriteColor - Destination Sprite Pointer (can be also the Source Sprite) (array of pixel data) ;; (1B C') height - Sprite Height in bytes (>0) ;; (1B B') width - Sprite Width in *bytes* (Beware, *not* in pixels!) +;; (1B L) oldColor - Color to replace +;; (1B H) newColor - New color ;; ;; Assembly call (Input parameters on registers): ;; > call cpct_spriteMaskedColorizeM0_asm @@ -55,17 +57,19 @@ ;; There is no practical upper limit to this value. Height of a sprite in ;; bytes and pixels is the same value, as bytes only group consecutive pixels in ;; the horizontal space. +;; * *oldColor* must be the index of color (0 to 15) to replace +;; * *newColor* must be the index of the new color (0 to 15) ;; ;; Known limitations: ;; * This function *will not work from ROM*, as it uses self-modifying code. ;; * This function requires the CPC firmware to be DISABLED. Otherwise, random crashes might happen due to side effects. ;; ;; Destroyed Register values: -;; AF, BC, DE, BC', DE', HL', IX +;; AF, BC, DE, HL, BC', DE', HL', IX ;; ;; Required memory: -;; C-bindings - 165 bytes -;; ASM-bindings - 160 bytes +;; C-bindings - 87 bytes +;; ASM-bindings - 73 bytes ;; ;; Time Measures: ;; (start code) @@ -88,19 +92,35 @@ ;; Thanks to all of them for their help and support. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -.globl _cpct_color_old -.globl _cpct_color_new +.globl dc_mode0_ct - ;; newColor to pixel format (E) - ld a, (_cpct_color_new);; [4] A = mem new color index +;; Macro to convert Pixel to xAxC xBxD format +.macro convertPixel + ;; From cpct_px2byteM0 + ld bc, #dc_mode0_ct ;; [3] BC points to conversion table (dc_mode0_ct) + + ;; Compute BC += A + add c ;; [1] | C += A + ld c, a ;; [1] | + sub a ;; [1] A = 0 (preserving Carry Flag) + adc b ;; [1] | B += Carry + ld b, a ;; [1] | + + ;; A = *(BC + A) + ld a, (bc) ;; [2] A = Value stored at the table pointed by BC +.endm + + ;; Convert newColor to pixel format (E) + ld a, h ;; [1] A = H new color index + convertPixel ;; [10] | Convert into A ld e, a ;; [1] | E = A new color : xAxC xBxD - ;; oldColor to pixel format (D) - ld a, (_cpct_color_old);; [4] A = mem old color index + ;; Convert oldColor to pixel format (D) + ld a, l ;; [1] A = L old color index + convertPixel ;; [10] | Convert into A ld d, a ;; [1] | D = A old color : xAxC xBxD ld c, #0x55 ;; [2] C = Mask to get pixel A : xAxC xBxD - exx ;; [1] Switch to Alternate registers ld__ixl_c ;; [1] IXL = C (Width) @@ -148,8 +168,8 @@ setByte: inc de ;; [2] Next byte sprite colorized djnz lineLoop ;; [3] Decrement B (Width) if != 0 goto lineLoop - dec c ;; [1] Decrement C (Height) - jr nz, convertLoop ;; [2/3] If C == O goto end + dec c ;; [1] Decrement C (Height) + jr nz, convertLoop ;; [2/3] If C == O goto end end: ;; Return is included in bindings \ No newline at end of file diff --git a/cpctelera/src/sprites/colorReplace/M0/cpct_spriteMaskedColorizeM0_asmbindings.s b/cpctelera/src/sprites/colorReplace/M0/cpct_spriteMaskedColorizeM0_asmbindings.s index af949e8a6..04b8fcf88 100644 --- a/cpctelera/src/sprites/colorReplace/M0/cpct_spriteMaskedColorizeM0_asmbindings.s +++ b/cpctelera/src/sprites/colorReplace/M0/cpct_spriteMaskedColorizeM0_asmbindings.s @@ -1,6 +1,6 @@ ;;-----------------------------LICENSE NOTICE------------------------------------ ;; This file is part of CPCtelera: An Amstrad CPC Game Engine -;; Copyright (C) 2018 Arnaud Bouche (Arnaud6128) +;; Copyright (C) 2018 Arnaud Bouche (@Arnaud6128) ;; Copyright (C) 2018 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) ;; ;; This program is free software: you can redistribute it and/or modify @@ -18,7 +18,7 @@ ;;------------------------------------------------------------------------------- .module cpct_sprites -.include "../macros/cpct_undocumentedOpcodes.s" +.include "../../../macros/cpct_undocumentedOpcodes.h.s" ;; ;; ASM bindings for <cpct_spriteMaskedColorizeM0> @@ -27,6 +27,7 @@ cpct_spriteMaskedColorizeM0_asm:: ;; Assembly entry point ;; GET Parameters from the stack ld (dms_restore_ix + 2), ix ;; [6] Save IX to restore it before returning + pop hl ;; [3] HL = Return Address .include /cpct_spriteMaskedColorizeM0.asm/ diff --git a/cpctelera/src/sprites/colorReplace/M0/cpct_spriteMaskedColorizeM0_cbindings.s b/cpctelera/src/sprites/colorReplace/M0/cpct_spriteMaskedColorizeM0_cbindings.s index c74a0ea07..3dad1ae84 100644 --- a/cpctelera/src/sprites/colorReplace/M0/cpct_spriteMaskedColorizeM0_cbindings.s +++ b/cpctelera/src/sprites/colorReplace/M0/cpct_spriteMaskedColorizeM0_cbindings.s @@ -18,7 +18,7 @@ ;;------------------------------------------------------------------------------- .module cpct_sprites -.include "../macros/cpct_undocumentedOpcodes.s" +.include "../../../macros/cpct_undocumentedOpcodes.h.s" ;; ;; C bindings for <cpct_spriteMaskedColorizeM0> @@ -29,7 +29,7 @@ _cpct_spriteMaskedColorizeM0:: ;; GET Parameters from the stack ld (dms_restore_ix + 2), ix ;; [6] Save IX to restore it before returning - pop de ;; [3] DE = Return Address + pop hl ;; [3] HL = Return Address exx pop hl ;; [3] HL' = Source address (Sprite) @@ -37,8 +37,9 @@ _cpct_spriteMaskedColorizeM0:: pop bc ;; [5] BC' = (B = Sprite Height, C = Width) exx - push de ;; [4] Put returning address in the stack again - ;; as this function uses __z88dk_callee convention + ex (sp), hl ;; [6] HL = (H = newColor, L = oldColor) + ;; ... and leave Return Address at (SP) as we don't need to restore + ;; ... stack status because callin convention is __z88dk_callee .include /cpct_spriteMaskedColorizeM0.asm/ diff --git a/cpctelera/src/sprites/colorReplace/colorReplace.h b/cpctelera/src/sprites/colorReplace/colorReplace.h index 79cc0f19a..d5675f624 100644 --- a/cpctelera/src/sprites/colorReplace/colorReplace.h +++ b/cpctelera/src/sprites/colorReplace/colorReplace.h @@ -28,20 +28,17 @@ #ifndef CPCT_COLORREPLACE_H #define CPCT_COLORREPLACE_H -// Function to set colors to replace M0 -extern void cpct_setReplaceColorsM0(u8 oldColor, u8 newColor) __z88dk_callee; - // Functions to replace a color in sprite M0 -extern void cpct_spriteColorizeM0(u8* sprite, u8* spriteColor, u8 width, u8 height) __z88dk_callee; -extern void cpct_spriteMaskedColorizeM0(u8* sprite, u8* spriteColor, u8 width, u8 height) __z88dk_callee; +extern void cpct_spriteColorizeM0(u8* sprite, u8* spriteColor, u8 width, u8 height, u8 oldColor, u8 newColor) __z88dk_callee; +extern void cpct_spriteMaskedColorizeM0(u8* sprite, u8* spriteColor, u8 width, u8 height, u8 oldColor, u8 newColor) __z88dk_callee; // Functions to draw a sprite M0 with a color replaced -extern void cpct_drawSpriteColorizeM0(u8* sprite, u8* destMem, u8 width, u8 height) __z88dk_callee; -extern void cpct_drawSpriteMaskedColorizeM0(u8* sprite, u8* destMem, u8 width, u8 height) __z88dk_callee; -extern void cpct_drawSpriteMaskedAlignedColorizeM0(u8* sprite, u8* destMem, u8 width, u8 height, const u8* maskTable) __z88dk_callee; +extern void cpct_drawSpriteColorizeM0(u8* sprite, u8* destMem, u8 width, u8 height, u8 oldColor, u8 newColor) __z88dk_callee; +extern void cpct_drawSpriteMaskedColorizeM0(u8* sprite, u8* destMem, u8 width, u8 height, u8 oldColor, u8 newColor) __z88dk_callee; +extern void cpct_drawSpriteMaskedAlignedColorizeM0(u8* sprite, u8* destMem, u8 width, u8 height, u8 oldColor, u8 newColor, const u8* maskTable) __z88dk_callee; // Functions to replace a color in sprite M1 -extern void cpct_spriteColorizeM1(u8* sprite, u8* spriteColor, u8 width, u8 height) __z88dk_callee; +extern void cpct_spriteColorizeM1(u8* sprite, u8* spriteColor, u8 width, u8 height, u8 oldColor, u8 newColor) __z88dk_callee; extern void cpct_spriteMaskedColorizeM1(u8* sprite, u8* spriteColor, u8 width, u8 height, u8 oldColor, u8 newColor) __z88dk_callee; // Functions to draw a sprite M1 with a color replaced diff --git a/examples/medium/colorReplace/src/drawing.c b/examples/medium/colorReplace/src/drawing.c index aa02f4f8a..414450594 100644 --- a/examples/medium/colorReplace/src/drawing.c +++ b/examples/medium/colorReplace/src/drawing.c @@ -1,8 +1,8 @@ //-----------------------------LICENSE NOTICE------------------------------------ // This file is part of CPCtelera: An Amstrad CPC Game Engine -// Copyright (C) 2017 Bouche Arnaud -// Copyright (C) 2017 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) +// Copyright (C) 2018 Bouche Arnaud (@Arnaud6128) +// Copyright (C) 2018 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Lesser General Public License as published by @@ -22,107 +22,104 @@ ///////////////////////////////////////////////////////////////////////////////// // GLOBAL VARIABLES -u8 gSpriteColorized[G_BALOON_W*G_BALOON_H]; // Array for sprite to color -u8 gBackGroundColor; // Background color -u8 gBaloonColor; // Current color baloon -u8 gPosCloud; // Position of cloude +u8 gSpriteColorized[G_BALOON_W*G_BALOON_H]; // Array for sprite to color +u8 gBackGroundColor; // Background color +u8 gBaloonColor; // Current color baloon +u8 gPosCloud; // Position of cloude ///////////////////////////////////////////////////////////////////////////////// // STRUCTURES DEFINITION -typedef struct TBaloon // Baloon structure +typedef struct TBaloon // Baloon structure { - i16 posY; // Absolute Baloon PosY (can be outside screen) - u8 posX; // Absolute Baloon PosX - - u8 drawPosY; // In screen Baloon PosY - u8 drawCY; // In screen Baloon Height - - u8 speed; // Baloon speed - u8 color; // Baloon color drawn - - u8 status; // Baloon status ACTIVE / INACTIVE + i16 posY; // Absolute Baloon PosY (can be outside screen) + u8 posX; // Absolute Baloon PosX + + u8 drawPosY; // In screen Baloon PosY + u8 drawCY; // In screen Baloon Height + + u8 speed; // Baloon speed + u8 color; // Baloon color drawn + + u8 status; // Baloon status ACTIVE / INACTIVE } SBaloon; -typedef struct TBaloons // All baloons structure +typedef struct TBaloons // All baloons structure { - u8 nb; // Nb baloons in screen - SBaloon baloons[NB_BALOONS]; // Array of baloon + u8 nb; // Nb baloons in screen + SBaloon baloons[NB_BALOONS]; // Array of baloon } SBaloons; -SBaloons gBaloons; // Baloons to draw +SBaloons gBaloons; // Baloons to draw -typedef struct TStar // Lighting star structure +typedef struct TStar // Lighting star structure { - u8 posX; // Screen PosX - u8 posY; // Screen PosY + u8 posX; // Screen PosX + u8 posY; // Screen PosY - u8 color; // Star color drawn + u8 color; // Star color drawn } SStar; -typedef struct TStars // All stars structure +typedef struct TStars // All stars structure { - SStar stars[NB_STARS]; // Array of stars + SStar stars[NB_STARS]; // Array of stars } SStars; -SStars gStars; // Stars to draw +SStars gStars; // Stars to draw /////////////////////////////////////////////////////// -/// GET RANDOM FROM 0 TO MAX-1 +/// GET RANDOM FROM 0 TO MAX-1 /// u8 GetRand(u8 max) { - return cpct_rand()%max; + return cpct_rand()%max; } /////////////////////////////////////////////////////// -/// CHANGE TWO COLORS OF BALOON SPRITE +/// CHANGE TWO COLORS OF BALOON SPRITE /// void ColorSprite(u8 color) { - // Replace the two colors 1 and 2 of sprite baloon - cpct_setReplaceColorsM0(1, color); - cpct_spriteColorizeM0(g_baloon, gSpriteColorized, G_BALOON_W, G_BALOON_H); // Colors are consecutives - - cpct_setReplaceColorsM0(2, color + 1); - cpct_spriteColorizeM0(gSpriteColorized, gSpriteColorized, G_BALOON_W, G_BALOON_H); + // Replace the two colors 1 and 2 of sprite baloon + cpct_spriteColorizeM0(g_baloon, gSpriteColorized, G_BALOON_W, G_BALOON_H, 1, color); // Colors are consecutives + cpct_spriteColorizeM0(gSpriteColorized, gSpriteColorized, G_BALOON_W, G_BALOON_H, 2, color + 1); } /////////////////////////////////////////////////////// -/// CLEAR BALOON BACKGROUND +/// CLEAR BALOON BACKGROUND /// void ClearBaloon(SBaloon* baloon) { - // If baloon in visible part of view - if (baloon->drawPosY < VIEW_DOWN) - { - u8* pvmem; - - // Compute size to be filled with background color - u8 clearCY = baloon->drawCY + BALOON_TRAIL; - - // Compute position to clear - u8 posDownClearY = baloon->drawPosY + clearCY; - if (posDownClearY > VIEW_DOWN) - clearCY = VIEW_DOWN - baloon->drawPosY; - - // Draw the box with background color to clear - pvmem = GetBackBufferPtr(baloon->posX, baloon->drawPosY); - cpct_drawSolidBox(pvmem, gBackGroundColor, G_BALOON_W, clearCY); - } + // If baloon in visible part of view + if (baloon->drawPosY < VIEW_DOWN) + { + u8* pvmem; + + // Compute size to be filled with background color + u8 clearCY = baloon->drawCY + BALOON_TRAIL; + + // Compute position to clear + u8 posDownClearY = baloon->drawPosY + clearCY; + if (posDownClearY > VIEW_DOWN) + clearCY = VIEW_DOWN - baloon->drawPosY; + + // Draw the box with background color to clear + pvmem = GetBackBufferPtr(baloon->posX, baloon->drawPosY); + cpct_drawSolidBox(pvmem, gBackGroundColor, G_BALOON_W, clearCY); + } } /////////////////////////////////////////////////////// -/// DELETE BALOON +/// DELETE BALOON /// void DeleteBaloons(SBaloon* baloons, SBaloon* baloonToDel, u8* nb) { - // Get last baloon in array - // Decrement number of remaining baloons in array - const SBaloon* lastBaloon = &baloons[--*nb]; - - // Replace baloon to be deleted with last baloon (if they are not the same) - if (baloonToDel != lastBaloon) - cpct_memcpy(baloonToDel, lastBaloon, sizeof(SBaloon)); + // Get last baloon in array + // Decrement number of remaining baloons in array + const SBaloon* lastBaloon = &baloons[--*nb]; + + // Replace baloon to be deleted with last baloon (if they are not the same) + if (baloonToDel != lastBaloon) + cpct_memcpy(baloonToDel, lastBaloon, sizeof(SBaloon)); } /////////////////////////////////////////////////////// @@ -130,85 +127,85 @@ void DeleteBaloons(SBaloon* baloons, SBaloon* baloonToDel, u8* nb) /// void UpdateBaloons() { - SBaloon* itBaloon = gBaloons.baloons; - u8 i; - - // Test if we can add a new baloon - if (gBaloons.nb < NB_BALOONS) - { - // Add new baloon at end of array - // Increment number of baloons in array - SBaloon* newBaloon = &gBaloons.baloons[gBaloons.nb++]; - - // Get random positions X and Y - newBaloon->posX = GetRand(SCREEN_CX - G_BALOON_W); - newBaloon->posY = SCREEN_CY - GetRand(40); - - // Get random speed - newBaloon->speed = GetRand(3) + 2; - - // Get circular next color 2 by 2 until 12 - gBaloonColor = (gBaloonColor + 2) % 12; - newBaloon->color = gBaloonColor + 1; - - // Set baloon ACTIVE - newBaloon->status = BALOON_ACTIVE; - } - - // Update all baloons - for (i = 0; i < gBaloons.nb; i++) - { - // If baloon active move and draw it - if (itBaloon->status == BALOON_ACTIVE) - { - // Test if whole baloon outside view - if (itBaloon->posY + G_BALOON_H < VIEW_TOP) - { - // Set baloon inactive - itBaloon->status = BALOON_INACTIVE; - // Clear baloon background - ClearBaloon(itBaloon); - } - else - { - // Move baloon to up according its speed - i16 posY = itBaloon->posY - itBaloon->speed; - itBaloon->posY = posY; + SBaloon* itBaloon = gBaloons.baloons; + u8 i; + + // Test if we can add a new baloon + if (gBaloons.nb < NB_BALOONS) + { + // Add new baloon at end of array + // Increment number of baloons in array + SBaloon* newBaloon = &gBaloons.baloons[gBaloons.nb++]; + + // Get random positions X and Y + newBaloon->posX = GetRand(SCREEN_CX - G_BALOON_W); + newBaloon->posY = SCREEN_CY - GetRand(40); + + // Get random speed + newBaloon->speed = GetRand(3) + 2; + + // Get circular next color 2 by 2 until 12 + gBaloonColor = (gBaloonColor + 2) % 12; + newBaloon->color = gBaloonColor + 1; + + // Set baloon ACTIVE + newBaloon->status = BALOON_ACTIVE; + } + + // Update all baloons + for (i = 0; i < gBaloons.nb; i++) + { + // If baloon active move and draw it + if (itBaloon->status == BALOON_ACTIVE) + { + // Test if whole baloon outside view + if (itBaloon->posY + G_BALOON_H < VIEW_TOP) + { + // Set baloon inactive + itBaloon->status = BALOON_INACTIVE; + // Clear baloon background + ClearBaloon(itBaloon); + } + else + { + // Move baloon to up according its speed + i16 posY = itBaloon->posY - itBaloon->speed; + itBaloon->posY = posY; - // Baloon outside view by top - if (posY < VIEW_TOP) - { - itBaloon->drawPosY = 0; - itBaloon->drawCY = G_BALOON_H + posY; - } - else - // Baloon outside view by down - if (posY + G_BALOON_H > VIEW_DOWN) - { - itBaloon->drawPosY = posY; - itBaloon->drawCY = VIEW_DOWN - posY; - } - // Baloon all in view - else - { - itBaloon->drawPosY = posY; - itBaloon->drawCY = G_BALOON_H; - } - } - } - // If inactive delete baloon - else - { - // Clear baloon background - ClearBaloon(itBaloon); - - // Delete baloon from list - DeleteBaloons(gBaloons.baloons, itBaloon, &gBaloons.nb); - } - - // Get next baloon pointer - itBaloon++; - } + // Baloon outside view by top + if (posY < VIEW_TOP) + { + itBaloon->drawPosY = 0; + itBaloon->drawCY = G_BALOON_H + posY; + } + else + // Baloon outside view by down + if (posY + G_BALOON_H > VIEW_DOWN) + { + itBaloon->drawPosY = posY; + itBaloon->drawCY = VIEW_DOWN - posY; + } + // Baloon all in view + else + { + itBaloon->drawPosY = posY; + itBaloon->drawCY = G_BALOON_H; + } + } + } + // If inactive delete baloon + else + { + // Clear baloon background + ClearBaloon(itBaloon); + + // Delete baloon from list + DeleteBaloons(gBaloons.baloons, itBaloon, &gBaloons.nb); + } + + // Get next baloon pointer + itBaloon++; + } } /////////////////////////////////////////////////////// @@ -216,27 +213,27 @@ void UpdateBaloons() /// void DrawBaloon(SBaloon* baloon, const u8* spriteBaloon) { - i16 posY = baloon->posY; - - // If baloon in view - if (posY + G_BALOON_H > VIEW_TOP && posY < VIEW_DOWN) - { - // Get VMem pointer of current baloon position - u8* pvmem = GetBackBufferPtr(baloon->posX, baloon->drawPosY); - const u8* sprite = (u8*)spriteBaloon; - - // Baloon partialy outside view by top - if (posY < VIEW_TOP) - { - // Compute Y position - u8 y = -posY; - - // Compute sprite offset - sprite = (u8*)spriteBaloon + G_BALOON_W * y; - } - - cpct_drawSpriteMaskedAlignedTable(sprite, pvmem, G_BALOON_W, baloon->drawCY, gMaskTable); - } + i16 posY = baloon->posY; + + // If baloon in view + if (posY + G_BALOON_H > VIEW_TOP && posY < VIEW_DOWN) + { + // Get VMem pointer of current baloon position + u8* pvmem = GetBackBufferPtr(baloon->posX, baloon->drawPosY); + const u8* sprite = (u8*)spriteBaloon; + + // Baloon partialy outside view by top + if (posY < VIEW_TOP) + { + // Compute Y position + u8 y = -posY; + + // Compute sprite offset + sprite = (u8*)spriteBaloon + G_BALOON_W * y; + } + + cpct_drawSpriteMaskedAlignedTable(sprite, pvmem, G_BALOON_W, baloon->drawCY, gMaskTable); + } } /////////////////////////////////////////////////////// @@ -244,45 +241,42 @@ void DrawBaloon(SBaloon* baloon, const u8* spriteBaloon) /// void DrawStars() { - // Static stars color - const static u8 sColorStar[NB_COLORS_STAR] = { 2, 4, 7, 8, 10, 11, 12 }; - static u8 color = 0; - - u8 i; - for (i = 0; i < NB_STARS; i++) - { - // Get video pointer of each star to be drawn - u8* pvmem = GetBackBufferPtr(gStars.stars[i].posX, gStars.stars[i].posY); - u8 color = gStars.stars[i].color++; - - // Set color to change - cpct_setReplaceColorsM0(15, sColorStar[color]); - - // Use different drawing color methods - if (i < NB_STARS/3) - { - // Color and draw masked sprite in video memory - cpct_drawSpriteMaskedColorizeM0(g_star_trans, pvmem, G_STAR_TRANS_W, G_STAR_TRANS_H); - } - else if (i > NB_STARS/3 && i < 2*NB_STARS/3) - { - // Color and draw masked aligned sprite in video memory - cpct_drawSpriteMaskedAlignedColorizeM0(g_square, pvmem, G_SQUARE_W, G_SQUARE_H, gMaskTable); - } - else - { - // Color and copy masked sprite in temporary array - u8 circleColor[G_CIRCLE_TRANS_W * G_CIRCLE_TRANS_H * 2]; - cpct_spriteMaskedColorizeM0(g_circle_trans, circleColor, G_CIRCLE_TRANS_W, G_CIRCLE_TRANS_H); - - // Draw masked Sprite from temporary array - cpct_drawSpriteMasked(circleColor, pvmem, G_CIRCLE_TRANS_W, G_CIRCLE_TRANS_H); - } - - // If all colors palette used restart from 0 - if (color == NB_COLORS_STAR - 1) - gStars.stars[i].color = 0; - } + // Static stars color + const static u8 sColorStar[NB_COLORS_STAR] = { 2, 4, 7, 8, 10, 11, 12 }; + static u8 color = 0; + + u8 i; + for (i = 0; i < NB_STARS; i++) + { + // Get video pointer of each star to be drawn + u8* pvmem = GetBackBufferPtr(gStars.stars[i].posX, gStars.stars[i].posY); + u8 color = gStars.stars[i].color++; + + // Use different drawing color methods + if (i < NB_STARS/3) + { + // Color and draw masked sprite in video memory + cpct_drawSpriteMaskedColorizeM0(g_star_trans, pvmem, G_STAR_TRANS_W, G_STAR_TRANS_H, 15, sColorStar[color]); + } + else if (i > NB_STARS/3 && i < 2*NB_STARS/3) + { + // Color and draw masked aligned sprite in video memory + cpct_drawSpriteMaskedAlignedColorizeM0(g_square, pvmem, G_SQUARE_W, G_SQUARE_H, 15, sColorStar[color], gMaskTable); + } + else + { + // Color and copy masked sprite in temporary array + u8 circleColor[G_CIRCLE_TRANS_W * G_CIRCLE_TRANS_H * 2]; + cpct_spriteMaskedColorizeM0(g_circle_trans, circleColor, G_CIRCLE_TRANS_W, G_CIRCLE_TRANS_H, 15, sColorStar[color]); + + // Draw masked Sprite from temporary array + cpct_drawSpriteMasked(circleColor, pvmem, G_CIRCLE_TRANS_W, G_CIRCLE_TRANS_H); + } + + // If all colors palette used restart from 0 + if (color == NB_COLORS_STAR - 1) + gStars.stars[i].color = 0; + } } /////////////////////////////////////////////////////// @@ -290,9 +284,9 @@ void DrawStars() /// void DrawCloud() { - // Draw cloud at fixed place - u8* pvmem = GetBackBufferPtr(0, POS_CLOUD_Y); - cpct_drawSprite(g_cloud, pvmem, G_CLOUD_W, G_CLOUD_H); + // Draw cloud at fixed place + u8* pvmem = GetBackBufferPtr(0, POS_CLOUD_Y); + cpct_drawSprite(g_cloud, pvmem, G_CLOUD_W, G_CLOUD_H); } /////////////////////////////////////////////////////// @@ -300,40 +294,35 @@ void DrawCloud() /// void DrawSceneBaloons() { - u8 i, color = 0; - - // Clear background for all baloons - SBaloon* itBaloon = gBaloons.baloons; // Get first baloon pointer - for (i = 0; i < gBaloons.nb; i++) - { - ClearBaloon(itBaloon); - itBaloon++; - } - - // Draw sprite cloud - DrawCloud(); - - // Draw all baloons - itBaloon = gBaloons.baloons; // Get first baloon pointer - for (i = 0; i < gBaloons.nb; i++) - { - const u8* sprite = g_baloon; // Default baloon sprite (blue) + u8 i; + + // Clear background for all baloons + SBaloon* itBaloon = gBaloons.baloons; // Get first baloon pointer + for (i = 0; i < gBaloons.nb; i++) + { + ClearBaloon(itBaloon); + itBaloon++; + } + + // Draw sprite cloud + DrawCloud(); + + // Draw all baloons + itBaloon = gBaloons.baloons; // Get first baloon pointer + for (i = 0; i < gBaloons.nb; i++) + { + const u8* sprite = g_baloon; // Default baloon sprite (blue) - // Test if sprite have colors to change - if (itBaloon->color > 1) // Color 0 (white) is transparent color - { - if (color != itBaloon->color) // Test if need to change Color of Sprite - { - color = itBaloon->color; - ColorSprite(color); // Change colors of ballon - } - - sprite = gSpriteColorized; // Sprite to draw is colorized baloon - } - - DrawBaloon(itBaloon, sprite); // Draw baloon sprite - itBaloon++; // Get next baloon - } + // Test if sprite have colors to change + if (itBaloon->color > 1) // Color 0 (white) is transparent color + { + ColorSprite(itBaloon->color); // Change colors of ballon + sprite = gSpriteColorized; // Sprite to draw is colorized baloon + } + + DrawBaloon(itBaloon, sprite); // Draw baloon sprite + itBaloon++; // Get next baloon + } } /////////////////////////////////////////////////////// @@ -341,21 +330,21 @@ void DrawSceneBaloons() /// void DrawBackground() { - u8* pvmem; - - // Fill video buffer with background color - cpct_memset((u8*)SCREEN_BUFF, gBackGroundColor, VMEM_SIZE); - - // Draw left part of Roof - pvmem = GetBackBufferPtr(0, SCREEN_CY-G_ROOF_H); - cpct_drawSprite(g_roof, pvmem, G_ROOF_W, G_ROOF_H); - - // Draw right part of Roof - pvmem += G_ROOF_W; - cpct_drawSprite(g_roof, pvmem, G_ROOF_W, G_ROOF_H); - - // Copy Same background on both buffers - cpct_memcpy(CPCT_VMEM_START, (u8*)SCREEN_BUFF, VMEM_SIZE); + u8* pvmem; + + // Fill video buffer with background color + cpct_memset((u8*)SCREEN_BUFF, gBackGroundColor, VMEM_SIZE); + + // Draw left part of Roof + pvmem = GetBackBufferPtr(0, SCREEN_CY-G_ROOF_H); + cpct_drawSprite(g_roof, pvmem, G_ROOF_W, G_ROOF_H); + + // Draw right part of Roof + pvmem += G_ROOF_W; + cpct_drawSprite(g_roof, pvmem, G_ROOF_W, G_ROOF_H); + + // Copy Same background on both buffers + cpct_memcpy(CPCT_VMEM_START, (u8*)SCREEN_BUFF, VMEM_SIZE); } ///////////////////////////////////////////////////////////////////////////////// @@ -365,18 +354,18 @@ void DrawBackground() /// void InitializeDrawing() { - u8 dx = SCREEN_CX / NB_STARS; // Compute space between stars - - u8 i; - for (i = 0; i < NB_STARS; i++) - { - gStars.stars[i].posX = dx * i + 5; // Constant space beetween stars - gStars.stars[i].posY = GetRand(10) + 175; // Random Y position from 175 to 184 - gStars.stars[i].color = GetRand(NB_COLORS_STAR); // Random color from 0 to NB_COLORS_STAR-1 - } - - gBackGroundColor = cpct_px2byteM0(14, 14); // Get byte color of background for M0 - gBaloons.nb = 0; // No baloon to draw at start - - DrawBackground(); // Set background on both buffers + u8 dx = SCREEN_CX / NB_STARS; // Compute space between stars + + u8 i; + for (i = 0; i < NB_STARS; i++) + { + gStars.stars[i].posX = dx * i + 5; // Constant space beetween stars + gStars.stars[i].posY = GetRand(10) + 175; // Random Y position from 175 to 184 + gStars.stars[i].color = GetRand(NB_COLORS_STAR); // Random color from 0 to NB_COLORS_STAR-1 + } + + gBackGroundColor = cpct_px2byteM0(14, 14); // Get byte color of background for M0 + gBaloons.nb = 0; // No baloon to draw at start + + DrawBackground(); // Set background on both buffers } From e5346e724b111b89c44a63f584ac0ae44ed5ac44 Mon Sep 17 00:00:00 2001 From: Arnaud <arnaud_bouche@hotmail.com> Date: Fri, 26 Jan 2018 22:41:37 +0100 Subject: [PATCH 30/31] Add new function cpct_setReplaceColors and update others --- .../M0/cpct_drawSpriteColorizeM0.asm | 41 +- .../cpct_drawSpriteColorizeM0_asmbindings.s | 7 +- .../M0/cpct_drawSpriteColorizeM0_cbindings.s | 15 +- ...cpct_drawSpriteMaskedAlignedColorizeM0.asm | 149 +++-- ...priteMaskedAlignedColorizeM0_asmbindings.s | 7 +- ...wSpriteMaskedAlignedColorizeM0_cbindings.s | 17 +- .../M0/cpct_drawSpriteMaskedColorizeM0.asm | 56 +- ...t_drawSpriteMaskedColorizeM0_asmbindings.s | 3 +- ...pct_drawSpriteMaskedColorizeM0_cbindings.s | 11 +- .../colorReplace/M0/cpct_replaceColor.s | 44 ++ .../M0/cpct_setReplaceColorsM0.asm | 87 +++ .../M0/cpct_setReplaceColorsM0_cbinding.s | 31 ++ .../colorReplace/M0/cpct_spriteColorizeM0.asm | 57 +- .../M0/cpct_spriteColorizeM0_asmbindings.s | 10 +- .../M0/cpct_spriteColorizeM0_cbindings.s | 15 +- .../M0/cpct_spriteMaskedColorizeM0.asm | 48 +- .../cpct_spriteMaskedColorizeM0_asmbindings.s | 5 +- .../cpct_spriteMaskedColorizeM0_cbindings.s | 9 +- .../src/sprites/colorReplace/colorReplace.h | 16 +- examples/medium/colorReplace/src/drawing.c | 526 +++++++++--------- 20 files changed, 605 insertions(+), 549 deletions(-) create mode 100644 cpctelera/src/sprites/colorReplace/M0/cpct_replaceColor.s create mode 100644 cpctelera/src/sprites/colorReplace/M0/cpct_setReplaceColorsM0.asm create mode 100644 cpctelera/src/sprites/colorReplace/M0/cpct_setReplaceColorsM0_cbinding.s diff --git a/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteColorizeM0.asm b/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteColorizeM0.asm index a40ef9e87..9ee49f27e 100644 --- a/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteColorizeM0.asm +++ b/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteColorizeM0.asm @@ -25,15 +25,13 @@ ;; Directly replace a color and draw a sprite to video memory. ;; ;; C Definition: -;; void <cpct_drawSpriteColorizeM0> (void* *sprite*, void* *memory*, <u8> *width*, <u8> *height*, <u8> *oldColor*, <u8> *newColor*) __z88dk_callee; +;; void <cpct_drawSpriteColorizeM0> (void* *sprite*, void* *memory*, <u8> *width*, <u8> *height*) __z88dk_callee; ;; ;; Input Parameters (8 bytes): ;; (2B HL') sprite - Source Sprite Pointer (array of pixel data) ;; (2B DE') memory - Destination video memory pointer ;; (1B C' ) height - Sprite Height in bytes (>0) ;; (1B B' ) width - Sprite Width in *bytes* (Beware, *not* in pixels!) -;; (1B L ) oldColor - Color to replace -;; (1B H ) newColor - New color ;; ;; Assembly call (Input parameters on registers): ;; > call cpct_drawSpriteColorizeM0_asm @@ -54,8 +52,6 @@ ;; There is no practical upper limit to this value. Height of a sprite in ;; bytes and pixels is the same value, as bytes only group consecutive pixels in ;; the horizontal space. -;; * *oldColor* must be the index of color (0 to 15) to replace -;; * *newColor* must be the index of the new color (0 to 15) ;; ;; Known limitations: ;; * This function does not do any kind of boundary check or clipping. If you @@ -76,8 +72,8 @@ ;; AF, BC, DE, HL, BC', DE', HL', IX ;; ;; Required memory: -;; C-bindings - 118 bytes -;; ASM-bindings - 108 bytes +;; C-bindings - 165 bytes +;; ASM-bindings - 160 bytes ;; ;; Time Measures: ;; (start code) @@ -100,32 +96,15 @@ ;; Thanks to all of them for their help and support. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -.globl dc_mode0_ct +.globl _cpct_color_old +.globl _cpct_color_new -;; Macro to convert Pixel to xAxC xBxD format -.macro convertPixel - ;; From cpct_px2byteM0 - ld bc, #dc_mode0_ct ;; [3] BC points to conversion table (dc_mode0_ct) - - ;; Compute BC += A - add c ;; [1] | C += A - ld c, a ;; [1] | - sub a ;; [1] A = 0 (preserving Carry Flag) - adc b ;; [1] | B += Carry - ld b, a ;; [1] | - - ;; A = *(BC + A) - ld a, (bc) ;; [2] A = Value stored at the table pointed by BC -.endm - - ;; Convert newColor to pixel format (E) - ld a, h ;; [1] A = H new color index - convertPixel ;; [10] | Convert into A + ;; newColor to pixel format (E) + ld a, (_cpct_color_new);; [4] A = mem new color index ld e, a ;; [1] | E = A new color : xAxC xBxD - ;; Convert oldColor to pixel format (D) - ld a, l ;; [1] A = L old color index - convertPixel ;; [10] | Convert into A + ;; oldColor to pixel format (D) + ld a, (_cpct_color_old);; [4] A = mem old color index ld d, a ;; [1] | D = A old color : xAxC xBxD ld c, #0x55 ;; [2] C = Mask to get pixel A : xAxC xBxD @@ -147,7 +126,7 @@ lineLoop: and c ;; [2] A |= C (C = 0x55) : xBxB xBxB cp d ;; [1] Test if pixel (A) is the old colour to be replaced (D) - jr nz, readPixelA ;; [2/3] If not equal go to next pixel + jr nz, readPixelA ;; [2/3] If not equal go to next pixel ld a, e ;; [1] else A = new colour to set (E) ;; Pixel Mode 0 = ABAB ABAB diff --git a/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteColorizeM0_asmbindings.s b/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteColorizeM0_asmbindings.s index cf824588a..01bfcad7c 100644 --- a/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteColorizeM0_asmbindings.s +++ b/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteColorizeM0_asmbindings.s @@ -1,7 +1,7 @@ ;;-----------------------------LICENSE NOTICE------------------------------------ ;; This file is part of CPCtelera: An Amstrad CPC Game Engine -;; Copyright (C) 2017 Arnaud Bouche (@Arnaud6128) -;; Copyright (C) 2017 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) +;; Copyright (C) 2018 Arnaud Bouche (@Arnaud6128) +;; Copyright (C) 2018 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) ;; ;; This program is free software: you can redistribute it and/or modify ;; it under the terms of the GNU Lesser General Public License as published by @@ -18,7 +18,7 @@ ;;------------------------------------------------------------------------------- .module cpct_sprites -.include "macros/cpct_undocumentedOpcodes.h.s" +.include "../macros/cpct_undocumentedOpcodes.s" ;; ;; ASM bindings for <cpct_drawSpriteColorizeM0> @@ -27,7 +27,6 @@ cpct_drawSpriteColorizeM0_asm:: ;; Assembly entry point ;; GET Parameters from the stack ld (dms_restore_ix + 2), ix ;; [6] Save IX to restore it before returning - pop hl ;; [3] HL = Return Address ;;.include /cpct_drawSpriteColorizeM0.asm/ diff --git a/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteColorizeM0_cbindings.s b/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteColorizeM0_cbindings.s index 0f273f27c..9b8ed88e2 100644 --- a/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteColorizeM0_cbindings.s +++ b/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteColorizeM0_cbindings.s @@ -1,7 +1,7 @@ ;;-----------------------------LICENSE NOTICE------------------------------------ ;; This file is part of CPCtelera: An Amstrad CPC Game Engine -;; Copyright (C) 2017 Arnaud Bouche (@Arnaud6128) -;; Copyright (C) 2017 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) +;; Copyright (C) 2018 Arnaud Bouche (@Arnaud6128) +;; Copyright (C) 2018 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) ;; ;; This program is free software: you can redistribute it and/or modify ;; it under the terms of the GNU Lesser General Public License as published by @@ -18,18 +18,18 @@ ;;------------------------------------------------------------------------------- .module cpct_sprites -.include "macros/cpct_undocumentedOpcodes.h.s" +.include "../macros/cpct_undocumentedOpcodes.s" ;; ;; C bindings for <cpct_drawSpriteColorizeM0> ;; -;; 33 us, 10 bytes +;; 33 us, 8 bytes ;; _cpct_drawSpriteColorizeM0:: ;; GET Parameters from the stack ld (dms_restore_ix + 2), ix ;; [6] Save IX to restore it before returning - pop hl ;; [3] HL = Return Address + pop de ;; [3] DE = Return Address exx pop hl ;; [3] HL' = Source address (Sprite) @@ -37,9 +37,8 @@ _cpct_drawSpriteColorizeM0:: pop bc ;; [5] BC' = (B = Sprite Height, C = Width) exx - ex (sp), hl ;; [6] HL = (H = newColor, L = oldColor) - ;; ... and leave Return Address at (SP) as we don't need to restore - ;; ... stack status because callin convention is __z88dk_callee + push de ;; [4] Put returning address in the stack again + ;; as this function uses __z88dk_callee convention .include /cpct_drawSpriteColorizeM0.asm/ diff --git a/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteMaskedAlignedColorizeM0.asm b/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteMaskedAlignedColorizeM0.asm index 981c21ab2..a0dda77a4 100644 --- a/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteMaskedAlignedColorizeM0.asm +++ b/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteMaskedAlignedColorizeM0.asm @@ -18,8 +18,6 @@ ;;------------------------------------------------------------------------------- .module cpct_sprites -.globl dc_mode0_ct - ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; Function: cpct_drawSpriteMaskedAlignedColorizeM0 @@ -28,15 +26,13 @@ ;; ;; C Definition: ;; void <cpct_drawSpriteMaskedAlignedColorizeM0> (void* *sprite*, void* *memory*, <u8> *width*, <u8> *height*, -;; <u8> *oldColor*, <u8> *newColor*, <u8*> *pmasktable*) __z88dk_callee; +;; <u8*> *pmasktable*) __z88dk_callee; ;; -;; Input Parameters (10 bytes): +;; Input Parameters (8 bytes): ;; (2B HL') sprite - Source Sprite Pointer (array of pixel data) ;; (2B DE') memory - Destination video memory pointer ;; (1B C' ) height - Sprite Height in bytes (>0) ;; (1B B' ) width - Sprite Width in *bytes* (Beware, *not* in pixels!) -;; (1B E ) oldColor - Color to replace -;; (1B D ) newColor - New color ;; (2B HL) pmasktable - Pointer to the aligned mask table used to create transparency ;; ;; Assembly call (Input parameters on registers): @@ -58,8 +54,6 @@ ;; There is no practical upper limit to this value. Height of a sprite in ;; bytes and pixels is the same value, as bytes only group consecutive pixels in ;; the horizontal space. -;; * *oldColor* must be the index of color (0 to 15) to replace -;; * *newColor* must be the index of the new color (0 to 15) ;; ;; Known limitations: ;; * This function does not do any kind of boundary check or clipping. If you @@ -80,8 +74,8 @@ ;; AF, BC, DE, HL, BC', DE', HL', IX ;; ;; Required memory: -;; C-bindings - 112 bytes -;; ASM-bindings - 96 bytes +;; C-bindings - 165 bytes +;; ASM-bindings - 160 bytes ;; ;; Time Measures: ;; (start code) @@ -104,97 +98,82 @@ ;; Thanks to all of them for their help and support. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; Macro to convert Pixel to xAxC xBxD format -.macro convertPixel - ;; From cpct_px2byteM0 - ld bc, #dc_mode0_ct ;; [3] BC points to conversion table (dc_mode0_ct) - - ;; Compute BC += A - add c ;; [1] | C += A - ld c, a ;; [1] | - sub a ;; [1] A = 0 (preserving Carry Flag) - adc b ;; [1] | B += Carry - ld b, a ;; [1] | - - ;; A = *(BC + A) - ld a, (bc) ;; [2] A = Value stored at the table pointed by BC -.endm +.globl _cpct_color_old +.globl _cpct_color_new - ;; Convert newColor to pixel format (E) - ld a, h ;; [1] A = H new color index - convertPixel ;; [10] | Convert into A + ;; newColor to pixel format (E) + ld a, (_cpct_color_new);; [4] A = mem new color index ld e, a ;; [1] | E = A new color : xAxC xBxD - ;; Convert oldColor to pixel format (D) - ld a, l ;; [1] A = L old color index - convertPixel ;; [10] | Convert into A - ld b, d - ld d, a ;; [1] | D = A old color : xAxC xBxD - - ld c, #0x55 ;; [2] C = Mask to get pixel A : xAxC xBxD - exx ;; [1] Switch to Alternate registers - - ld__ixl_c ;; [1] IXL = C (Width) - ld c, b ;; [1] C = B (Height) - -convertLoop: - push de ;; [4] Store DE start line (DestMem) - ld__b_ixl ;; [2] B = IXL (Sprite Width) + ;; oldColor to pixel format (D) + ld a, (_cpct_color_old);; [4] A = mem old color index + ld b, d ;; [1] B = D (Masked table adress High Byte) + ld d, a ;; [1] | D = A old color : xAxC xBxD + + ld c, #0x55 ;; [2] C = Mask to get pixel A : xAxC xBxD + exx ;; [1] Switch to Alternate registers + + ld__ixl_c ;; [1] IXL = C (Width) + ld c, b ;; [1] C = B (Height) + +convertLoop: + push de ;; [4] Store DE start line (DestMem) + ld__b_ixl ;; [2] B = IXL (Sprite Width) lineLoop: - ld a, (hl) ;; [2] A = (HL) current Byte of sprite + ld a, (hl) ;; [2] A = (HL) current Byte of sprite exx ;; [1] Switch to Default registers - - ld l, a ;; [1] L = A current Byte of sprite : ABAB ABAB - and c ;; [2] A |= C (C = 0x55) : xBxB xBxB - - cp d ;; [1] Test if pixel (A) is the old colour to be replaced (D) - jr nz, readPixelA ;; [2/3] If not equal go to next pixel + + ld l, a ;; [1] L = A current Byte of sprite : ABAB ABAB + and c ;; [2] A |= C (C = 0x55) : xBxB xBxB + + cp d ;; [1] Test if pixel (A) is the old colour to be replaced (D) + jr nz, readPixelA ;; [2/3] If not equal go to next pixel ld a, e ;; [1] else A = new colour to set (E) ;; Pixel Mode 0 = ABAB ABAB readPixelA: - ld h, a ;; [1] H = A (current colorized sprite) : xBxB xBxB - ld a, l ;; [1] L = A current Byte of sprite : ABAB ABAB - rrca ;; [1] A (current byte of sprite) >> 1 : ABAB ABAB -> xABA BABA - and c ;; [2] A |= Mask (0x55) : xAxA xAxA - - cp d ;; [1] Test if pixel (A) is the old colour to be replaced (D) - jr nz, readPixelB ;; [2/3] If not equal go to next pixel + ld h, a ;; [1] H = A (current colorized sprite) : xBxB xBxB + ld a, l ;; [1] L = A current Byte of sprite : ABAB ABAB + rrca ;; [1] A (current byte of sprite) >> 1 : ABAB ABAB -> xABA BABA + and c ;; [2] A |= Mask (0x55) : xAxA xAxA + + cp d ;; [1] Test if pixel (A) is the old colour to be replaced (D) + jr nz, readPixelB ;; [2/3] If not equal go to next pixel ld a, e ;; [1] else A = new colour to set (E) - + readPixelB: - rlca ;; [1] A = xAxA xAxA << 1 : AxAx AxAx - or h ;; [1] A |= H (xBxB xBxB) : ABAB ABAB + rlca ;; [1] A = xAxA xAxA << 1 : AxAx AxAx + or h ;; [1] A |= H (xBxB xBxB) : ABAB ABAB drawByte: ld h, b ;; [1] H = B (Masked table adress High Byte) - ld l, a ;; [1] Access mask table element (table must be 256-byte aligned) - exx ;; [1] Switch to Alternate registers - - ld a, (de) ;; [2] Get the value of the byte of the screen where we are going to draw - exx ;; [1] Switch to Default registers - - and (hl) ;; [2] Erase background part that is to be overwritten (Mask step 1) - or l ;; [1] Add up background and sprite information in one byte (Mask step 2) - exx ;; [1] Switch to Alternate registers - - ld (de), a ;; [2] Save modified background + sprite data information into memory + ld l, a ;; [1] Access mask table element (table must be 256-byte aligned) + exx ;; [1] Switch to Alternate registers + + ld a, (de) ;; [2] Get the value of the byte of the screen where we are going to draw + exx ;; [1] Switch to Default registers + + and (hl) ;; [2] Erase background part that is to be overwritten (Mask step 1) + or l ;; [1] Add up background and sprite information in one byte (Mask step 2) + exx ;; [1] Switch to Alternate registers + + ld (de), a ;; [2] Save modified background + sprite data information into memory - inc hl ;; [2] Next byte sprite source - inc de ;; [2] Next byte sprite colorized - djnz lineLoop ;; [3] Decrement B (Width) if B != 0 goto lineLoop - - dec c ;; [1] Decrement C (Height) - jr z, end ;; [2/3] If C == O goto end + inc hl ;; [2] Next byte sprite source + inc de ;; [2] Next byte sprite colorized + djnz lineLoop ;; [3] Decrement B (Width) if B != 0 goto lineLoop + + dec c ;; [1] Decrement C (Height) + jr z, end ;; [2/3] If C == O goto end - pop de ;; [3] Restore DE start line (DestMem) + pop de ;; [3] Restore DE start line (DestMem) ld a, d ;; [1] Start of next pixel line normally is 0x0800 bytes away. add #0x08 ;; [2] so we add it to DE (just by adding 0x08 to D) ld d, a ;; [1] - and #0x38 ;; [2] We check if we have crossed memory boundary (every 8 pixel lines).. - + and #0x38 ;; [2] We check if we have crossed memory boundary (every 8 pixel lines).. + jr nz, convertLoop ;; [2/3] .. by checking the 4 bits that identify present memory line. ;; .... If 0, we have crossed boundaries @@ -205,11 +184,11 @@ dms_sprite_8bit_boundary_crossed: ld a, d ;; [1] -- which effectively is the same as moving it 1 bank backwards and then adc #0xC0 ;; [2] -- 50 bytes forwards (which is what we want to move it to the next pixel line) ld d, a ;; [1] -- Calculations are made with 8 bit maths as it is faster than other alternatives here - - jr convertLoop ;; [3] Jump to continue with next pixel line + + jr convertLoop ;; [3] Jump to continue with next pixel line end: pop de ;; [3] Empty stack by getting last element (DestMem) - ;; Return is included in bindings - - + ;; Return is included in bindings + + diff --git a/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteMaskedAlignedColorizeM0_asmbindings.s b/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteMaskedAlignedColorizeM0_asmbindings.s index 12697cf2f..868def72a 100644 --- a/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteMaskedAlignedColorizeM0_asmbindings.s +++ b/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteMaskedAlignedColorizeM0_asmbindings.s @@ -1,7 +1,7 @@ ;;-----------------------------LICENSE NOTICE------------------------------------ ;; This file is part of CPCtelera: An Amstrad CPC Game Engine -;; Copyright (C) 2017 Arnaud Bouche (@Arnaud6128) -;; Copyright (C) 2017 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) +;; Copyright (C) 2018 Arnaud Bouche (@Arnaud6128) +;; Copyright (C) 2018 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) ;; ;; This program is free software: you can redistribute it and/or modify ;; it under the terms of the GNU Lesser General Public License as published by @@ -18,7 +18,7 @@ ;;------------------------------------------------------------------------------- .module cpct_sprites -.include "macros/cpct_undocumentedOpcodes.h.s" +.include "../macros/cpct_undocumentedOpcodes.s" ;; ;; ASM bindings for <cpct_drawSpriteMaskedAlignedColorizeM0> @@ -27,7 +27,6 @@ cpct_drawSpriteMaskedAlignedColorizeM0_asm:: ;; Assembly entry point ;; GET Parameters from the stack ld (dms_restore_ix + 2), ix ;; [6] Save IX to restore it before returning - pop hl ;; [3] HL = Return Address .include /cpct_drawSpriteMaskedAlignedColorizeM0.asm/ diff --git a/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteMaskedAlignedColorizeM0_cbindings.s b/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteMaskedAlignedColorizeM0_cbindings.s index 3e9a1ed13..01d9eee57 100644 --- a/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteMaskedAlignedColorizeM0_cbindings.s +++ b/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteMaskedAlignedColorizeM0_cbindings.s @@ -1,7 +1,7 @@ ;;-----------------------------LICENSE NOTICE------------------------------------ ;; This file is part of CPCtelera: An Amstrad CPC Game Engine -;; Copyright (C) 2017 Arnaud Bouche (Arnaud6128) -;; Copyright (C) 2017 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) +;; Copyright (C) 2018 Arnaud Bouche (@Arnaud6128) +;; Copyright (C) 2018 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) ;; ;; This program is free software: you can redistribute it and/or modify ;; it under the terms of the GNU Lesser General Public License as published by @@ -18,12 +18,12 @@ ;;------------------------------------------------------------------------------- .module cpct_sprites -.include "macros/cpct_undocumentedOpcodes.h.s" +.include "../macros/cpct_undocumentedOpcodes.s" ;; ;; C bindings for <cpct_drawSpriteMaskedAlignedColorizeM0> ;; -;; 39 us, 16 bytes +;; 39 us, 8 bytes ;; _cpct_drawSpriteMaskedAlignedColorizeM0:: @@ -37,13 +37,10 @@ _cpct_drawSpriteMaskedAlignedColorizeM0:: pop bc ;; [5] BC' = (B = Sprite Height, C = Width) exx ;; [1] Switch to Default registers - pop de ;; [3] DE = (D = newColor, E = oldColor) + pop de ;; [3] DE = Table Mask address - ex (sp), hl ;; [6] HL = Table Mask address - ;; ... and leave Return Address at (SP) as we don't need to restore - ;; ... stack status because callin convention is __z88dk_callee - - ex de, hl ;; [1] HL <-> DE + push hl ;; [4] Put returning address in the stack again + ;; as this function uses __z88dk_callee convention .include /cpct_drawSpriteMaskedAlignedColorizeM0.asm/ diff --git a/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteMaskedColorizeM0.asm b/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteMaskedColorizeM0.asm index 8f63f4c99..7862cdaeb 100644 --- a/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteMaskedColorizeM0.asm +++ b/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteMaskedColorizeM0.asm @@ -1,7 +1,7 @@ ;;-----------------------------LICENSE NOTICE------------------------------------ ;; This file is part of CPCtelera: An Amstrad CPC Game Engine -;; Copyright (C) 2017 Arnaud Bouche -;; Copyright (C) 2017 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) +;; Copyright (C) 2018 Arnaud Bouche (@Arnaud6128) +;; Copyright (C) 2018 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) ;; ;; This program is free software: you can redistribute it and/or modify ;; it under the terms of the GNU Lesser General Public License as published by @@ -18,8 +18,6 @@ ;;------------------------------------------------------------------------------- .module cpct_sprites -.globl dc_mode0_ct - ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; Function: cpct_drawSpriteMaskedColorizeM0 @@ -27,15 +25,13 @@ ;; Directly replace a color and draw a sprite Masked to video memory. ;; ;; C Definition: -;; void <cpct_drawSpriteMaskedColorizeM0> (void* *sprite*, void* *memory*, <u8> *width*, <u8> *height*, <u8> *oldColor*, <u8> *newColor*) __z88dk_callee; +;; void <cpct_drawSpriteMaskedColorizeM0> (void* *sprite*, void* *memory*, <u8> *width*, <u8> *height*) __z88dk_callee; ;; -;; Input Parameters (8 bytes): +;; Input Parameters (6 bytes): ;; (2B HL') sprite - Source Sprite Pointer (array of pixel data) ;; (2B DE') memory - Destination video memory pointer ;; (1B C' ) height - Sprite Height in bytes (>0) ;; (1B B' ) width - Sprite Width in *bytes* (Beware, *not* in pixels!) -;; (1B L ) oldColor - Color to replace -;; (1B H ) newColor - New color ;; ;; Assembly call (Input parameters on registers): ;; > call cpct_drawSpriteMaskedColorizeM0_asm @@ -61,8 +57,6 @@ ;; There is no practical upper limit to this value. Height of a sprite in ;; bytes and pixels is the same value, as bytes only group consecutive pixels in ;; the horizontal space. -;; * *oldColor* must be the index of color (0 to 15) to replace -;; * *newColor* must be the index of the new color (0 to 15) ;; ;; Known limitations: ;; * This function does not do any kind of boundary check or clipping. If you @@ -80,20 +74,21 @@ ;; * This function requires the CPC firmware to be DISABLED. Otherwise, random crashes might happen due to side effects. ;; ;; Destroyed Register values: -;; AF, BC, DE, HL, BC', DE', HL', IX +;; AF, BC, DE, BC', DE', HL', IX ;; ;; Required memory: -;; C-bindings - 115 bytes -;; ASM-bindings - 102 bytes +;; C-bindings - 165 bytes +;; ASM-bindings - 160 bytes ;; ;; Time Measures: ;; (start code) ;; Case | microSecs (us) | CPU Cycles ;; ---------------------------------------------------------------- -;; Best | 29 + (50 + 36W)H | 116 + (200 + 144W)H +;; Best | | +;; Worst | | ;; ---------------------------------------------------------------- -;; W=2,H=16 | 1981 | 7924 -;; W=4,H=32 | 6237 | 24948 +;; W=2,H=16 | | +;; W=4,H=32 | | ;; ---------------------------------------------------------------- ;; Asm saving | -16 | -64 ;; ---------------------------------------------------------------- @@ -107,34 +102,21 @@ ;; Thanks to all of them for their help and support. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; Macro to convert Pixel to xAxC xBxD format -.macro convertPixel - ;; From cpct_px2byteM0 - ld bc, #dc_mode0_ct ;; [3] BC points to conversion table (dc_mode0_ct) - - ;; Compute BC += A - add c ;; [1] | C += A - ld c, a ;; [1] | - sub a ;; [1] A = 0 (preserving Carry Flag) - adc b ;; [1] | B += Carry - ld b, a ;; [1] | - - ;; A = *(BC + A) - ld a, (bc) ;; [2] A = Value stored at the table pointed by BC -.endm +.globl _cpct_color_old +.globl _cpct_color_new - ;; Convert newColor to pixel format (E) - ld a, h ;; [1] A = H new color index - convertPixel ;; [10] | Convert into A + ;; newColor to pixel format (E) + ld a, (_cpct_color_new);; [4] A = mem new color index ld e, a ;; [1] | E = A new color : xAxC xBxD - ;; Convert oldColor to pixel format (D) - ld a, l ;; [1] A = L old color index - convertPixel ;; [10] | Convert into A + ;; oldColor to pixel format (D) + ld a, (_cpct_color_old);; [4] A = mem old color index ld d, a ;; [1] | D = A old color : xAxC xBxD ld c, #0x55 ;; [2] C = Mask to get pixel A : xAxC xBxD + ld c, #0x55 ;; [2] C = Mask to get pixel A : xAxC xBxD + exx ;; [1] Switch to Alternate registers ld__ixl_c ;; [1] IXL = C (Width) diff --git a/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteMaskedColorizeM0_asmbindings.s b/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteMaskedColorizeM0_asmbindings.s index 17aa2495b..a8806e008 100644 --- a/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteMaskedColorizeM0_asmbindings.s +++ b/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteMaskedColorizeM0_asmbindings.s @@ -18,7 +18,7 @@ ;;------------------------------------------------------------------------------- .module cpct_sprites -.include "macros/cpct_undocumentedOpcodes.h.s" +.include "../macros/cpct_undocumentedOpcodes.s" ;; ;; ASM bindings for <cpct_drawSpriteMaskedColorizeM0> @@ -27,7 +27,6 @@ cpct_drawSpriteMaskedColorizeM0_asm:: ;; Assembly entry point ;; GET Parameters from the stack ld (dms_restore_ix + 2), ix ;; [6] Save IX to restore it before returning - pop hl ;; [3] HL = Return Address .include /cpct_drawSpriteMaskedColorizeM0.asm/ diff --git a/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteMaskedColorizeM0_cbindings.s b/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteMaskedColorizeM0_cbindings.s index a9cc0cb72..1f0fd6e66 100644 --- a/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteMaskedColorizeM0_cbindings.s +++ b/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteMaskedColorizeM0_cbindings.s @@ -18,18 +18,18 @@ ;;------------------------------------------------------------------------------- .module cpct_sprites -.include "macros/cpct_undocumentedOpcodes.h.s" +.include "../macros/cpct_undocumentedOpcodes.s" ;; ;; C bindings for <cpct_drawSpriteMaskedColorizeM0> ;; -;; 33 us, 13 bytes +;; 33 us, 8 bytes ;; _cpct_drawSpriteMaskedColorizeM0:: ;; GET Parameters from the stack ld (dms_restore_ix + 2), ix ;; [6] Save IX to restore it before returning - pop hl ;; [3] HL = Return Address + pop de ;; [3] DE = Return Address exx pop hl ;; [3] HL' = Source address (Sprite) @@ -37,9 +37,8 @@ _cpct_drawSpriteMaskedColorizeM0:: pop bc ;; [5] BC' = (B = Sprite Height, C = Width) exx - ex (sp), hl ;; [6] HL = (H = newColor, L = oldColor) - ;; ... and leave Return Address at (SP) as we don't need to restore - ;; ... stack status because callin convention is __z88dk_callee + push de ;; [4] Put returning address in the stack again + ;; as this function uses __z88dk_callee convention .include /cpct_drawSpriteMaskedColorizeM0.asm/ diff --git a/cpctelera/src/sprites/colorReplace/M0/cpct_replaceColor.s b/cpctelera/src/sprites/colorReplace/M0/cpct_replaceColor.s new file mode 100644 index 000000000..260c2ea15 --- /dev/null +++ b/cpctelera/src/sprites/colorReplace/M0/cpct_replaceColor.s @@ -0,0 +1,44 @@ +;;-----------------------------LICENSE NOTICE------------------------------------ +;; This file is part of CPCtelera: An Amstrad CPC Game Engine +;; Copyright (C) 2018 Arnaud Bouche (@Arnaud6128) +;; Copyright (C) 2018 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) +;; +;; This program is free software: you can redistribute it and/or modify +;; it under the terms of the GNU Lesser General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU Lesser General Public License for more details. +;; +;; You should have received a copy of the GNU Lesser General Public License +;; along with this program. If not, see <http://www.gnu.org/licenses/>. +;;------------------------------------------------------------------------------- +.module cpct_sprites + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; +;; Variables: cpct_color_old, cpct_color_new +;; +;; Contains the colors to be used by theses functions: +;; * cpct_setReplaceColors +;; * cpct_spriteColorizeM0 +;; * cpct_spriteColorizeM1 +;; * cpct_drawSpriteColorizeM0 +;; * cpct_drawSpriteColorizeM1 +;; +;; C Definition: +;; <u8> <cpct_color_old>; +;; <u8> <cpct_color_new>; +;; +;; Known limitations: +;; * These color are used for Mode0 (0 to 15) and Mode1 (0 to 3) +;; * You may assing a value to this seed direcly from C or ASM. If directly accessed +;; from ASM, do not forget to put an underscore in front (_cpct_color_old and _cpct_color_new). +;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +_cpct_color_old:: .db #00 +_cpct_color_new:: .db #00 \ No newline at end of file diff --git a/cpctelera/src/sprites/colorReplace/M0/cpct_setReplaceColorsM0.asm b/cpctelera/src/sprites/colorReplace/M0/cpct_setReplaceColorsM0.asm new file mode 100644 index 000000000..47c9308a7 --- /dev/null +++ b/cpctelera/src/sprites/colorReplace/M0/cpct_setReplaceColorsM0.asm @@ -0,0 +1,87 @@ +;;-----------------------------LICENSE NOTICE------------------------------------ +;; This file is part of CPCtelera: An Amstrad CPC Game Engine +;; Copyright (C) 2018 Arnaud Bouche (@Arnaud6128) +;; Copyright (C) 2018 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) +;; +;; This program is free software: you can redistribute it and/or modify +;; it under the terms of the GNU Lesser General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU Lesser General Public License for more details. +;; +;; You should have received a copy of the GNU Lesser General Public License +;; along with this program. If not, see <http://www.gnu.org/licenses/>. +;;------------------------------------------------------------------------------- +.module cpct_sprites + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; +;; Function: cpct_setReplaceColorsM0 +;; +;; Sets the colors to be used with the replace colors for Mode 0 functions +;; +;; C Definition: +;; void <cpct_setReplaceColorsM0> (<u8> *oldColor*, <u8> *newColor*) __z88dk_fastcall; +;; +;; Input Parameters (2 bytes): +;; (1B D) *oldColor* - Color to be replaced. +;; (1B E) *newColor* - Color to set. +;; +;; Assembly call: +;; > call cpct_setReplaceColorsM0 +;; +;; Parameter Restrictions: +;; * There is not check on the color value according to the Mode 0 (0 to 15) +;; +;; Destroyed Register values: +;; A, BC, DE +;; +;; Required memory: +;; 8 bytes +;; +;; Time Measures: +;; (start code) +;; Case | microSecs (us) | CPU Cycles +;; ----------------------------------------- +;; Any | 14 | 56 +;; ----------------------------------------- +;; (end code) +;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +.globl dc_mode0_ct + +;; Macro to convert Pixel to xAxC xBxD format +.macro convertPixel + ;; From cpct_px2byteM0 + ld bc, #dc_mode0_ct ;; [3] BC points to conversion table (dc_mode0_ct) + + ;; Compute BC += A + add c ;; [1] | C += A + ld c, a ;; [1] | + sub a ;; [1] A = 0 (preserving Carry Flag) + adc b ;; [1] | B += Carry + ld b, a ;; [1] | + + ;; A = *(BC + A) + ld a, (bc) ;; [2] A = Value stored at the table pointed by BC +.endm + +.globl _cpct_color_old +.globl _cpct_color_new + + ;; Convert New color + ld a, h ;; [1] A = H new color + convertPixel ;; [10] | Convert into A + ld (_cpct_color_new), a ;; [3] | store color in memory + + ;; Convert Old color + ld a, l ;; [1] A = L old color + convertPixel ;; [10] | Convert into A + ld (_cpct_color_old), a ;; [3] | store color in memory + + ret ;; [3] \ No newline at end of file diff --git a/cpctelera/src/sprites/colorReplace/M0/cpct_setReplaceColorsM0_cbinding.s b/cpctelera/src/sprites/colorReplace/M0/cpct_setReplaceColorsM0_cbinding.s new file mode 100644 index 000000000..5792fed64 --- /dev/null +++ b/cpctelera/src/sprites/colorReplace/M0/cpct_setReplaceColorsM0_cbinding.s @@ -0,0 +1,31 @@ +;;-----------------------------LICENSE NOTICE------------------------------------ +;; This file is part of CPCtelera: An Amstrad CPC Game Engine +;; Copyright (C) 2018 Arnaud Bouche (@Arnaud6128) +;; Copyright (C) 2018 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) +;; +;; This program is free software: you can redistribute it and/or modify +;; it under the terms of the GNU Lesser General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU Lesser General Public License for more details. +;; +;; You should have received a copy of the GNU Lesser General Public License +;; along with this program. If not, see <http://www.gnu.org/licenses/>. +;;------------------------------------------------------------------------------- +.module cpct_sprites + +;; +;; C bindings for <cpct_px2byteM0> +;; +;; 9 us, 2 bytes +;; +_cpct_setReplaceColorsM0:: + ;; Recover parameters from the stack + pop hl ;; [3] HL = Return Address + ex (sp), hl ;; [6] HL => L : Old Color, H : New Color + +.include /cpct_setReplaceColorsM0.asm/ \ No newline at end of file diff --git a/cpctelera/src/sprites/colorReplace/M0/cpct_spriteColorizeM0.asm b/cpctelera/src/sprites/colorReplace/M0/cpct_spriteColorizeM0.asm index f319db09c..a6d9090c0 100644 --- a/cpctelera/src/sprites/colorReplace/M0/cpct_spriteColorizeM0.asm +++ b/cpctelera/src/sprites/colorReplace/M0/cpct_spriteColorizeM0.asm @@ -25,15 +25,13 @@ ;; Replace a color in a sprite and copy to another or the same sprite. ;; ;; C Definition: -;; void <cpct_spriteColorizeM0> (void* *sprite*, void* *spriteColor*, <u8> *width*, <u8> *height*, <u8> *oldColor*, <u8> *newColor*) __z88dk_callee; +;; void <cpct_spriteColorizeM0> (void* *sprite*, void* *spriteColor*, <u8> *width*, <u8> *height*) __z88dk_callee; ;; ;; Input Parameters (6 bytes): ;; (2B HL') sprite - Source Sprite Pointer (array of pixel data) ;; (2B DE') spriteColor - Destination Sprite Pointer (can be also the Source Sprite) (array of pixel data) ;; (1B C' ) height - Sprite Height in bytes (>0) ;; (1B B' ) width - Sprite Width in *bytes* (Beware, *not* in pixels!) -;; (1B L ) oldColor - Color to replace -;; (1B H ) newColor - New color ;; ;; Assembly call (Input parameters on registers): ;; > call cpct_spriteColorizeM0_asm @@ -51,33 +49,31 @@ ;; There is no practical upper limit to this value. Height of a sprite in ;; bytes and pixels is the same value, as bytes only group consecutive pixels in ;; the horizontal space. -;; * *oldColor* must be the index of color (0 to 15) to replace -;; * *newColor* must be the index of the new color (0 to 15) ;; ;; Known limitations: ;; * This function *will not work from ROM*, as it uses self-modifying code. ;; * This function requires the CPC firmware to be DISABLED. Otherwise, random crashes might happen due to side effects. ;; ;; Destroyed Register values: -;; AF, BC, DE, HL, BC', DE', HL', IX +;; AF, BC, DE, BC', DE', HL', IX ;; ;; Required memory: -;; C-bindings - 81 bytes -;; ASM-bindings - 67 bytes +;; C-bindings - 165 bytes +;; ASM-bindings - 160 bytes ;; ;; Time Measures: ;; (start code) ;; Case | microSecs (us) | CPU Cycles ;; ---------------------------------------------------------------- -;; | 29 + (6 + 33W)H | 116 + (24 + 132W)H +;; | 29 + (33 + 4W)H | 116 + (132 + 16W)H ;; ---------------------------------------------------------------- -;; W=2,H=16 | 1181 | 4724 -;; W=4,H=32 | 4445 | 17780 +;; W=2,H=16 | 685 | 2740 +;; W=4,H=32 | 1597 | 6388 ;; ---------------------------------------------------------------- ;; Asm saving | -16 | -64 ;; ---------------------------------------------------------------- ;; (end code) -;; W = *width* in bytes, H = *height* in bytes +;; W = *width* in bytes, H = *height* in bytes, HH = [(H-1)/8] ;; ;; Credits: ;; Original routine optimized by @Docent and discussed in CPCWiki : @@ -86,35 +82,19 @@ ;; Thanks to all of them for their help and support. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -.globl dc_mode0_ct +.globl _cpct_color_old +.globl _cpct_color_new -;; Macro to convert Pixel to xAxC xBxD format -.macro convertPixel - ;; From cpct_px2byteM0 - ld bc, #dc_mode0_ct ;; [3] BC points to conversion table (dc_mode0_ct) - - ;; Compute BC += A - add c ;; [1] | C += A - ld c, a ;; [1] | - sub a ;; [1] A = 0 (preserving Carry Flag) - adc b ;; [1] | B += Carry - ld b, a ;; [1] | - - ;; A = *(BC + A) - ld a, (bc) ;; [2] A = Value stored at the table pointed by BC -.endm - - ;; Convert newColor to pixel format (E) - ld a, h ;; [1] A = H new color index - convertPixel ;; [10] | Convert into A + ;; newColor to pixel format (E) + ld a, (_cpct_color_new);; [4] A = mem new color index ld e, a ;; [1] | E = A new color : xAxC xBxD - ;; Convert oldColor to pixel format (D) - ld a, l ;; [1] A = L old color index - convertPixel ;; [10] | Convert into A + ;; oldColor to pixel format (D) + ld a, (_cpct_color_old);; [4] A = mem old color index ld d, a ;; [1] | D = A old color : xAxC xBxD ld c, #0x55 ;; [2] C = Mask to get pixel A : xAxC xBxD + exx ;; [1] Switch to Alternate registers ld__ixl_c ;; [1] IXL = C (Width) @@ -124,7 +104,7 @@ convertLoop: ld__b_ixl ;; [2] B = IXL (Sprite Width) lineLoop: - ld a, (hl) ;; [2] A = (HL) current Byte of sprite + ld a, (hl) ;; [2] A = (HL') current Byte of sprite exx ;; [1] Switch to Default registers ld l, a ;; [1] L = A current Byte of sprite : ABAB ABAB @@ -159,8 +139,7 @@ setByte: nextLine: dec c ;; [1] Decrement C (Height) - jr nz, convertLoop ;; [2/3] If != O goto convertLoop + jr nz, convertLoop ;; [1] If != O goto convertLoop end: - ;; Return is included in bindings - + ;; Return is included in bindings \ No newline at end of file diff --git a/cpctelera/src/sprites/colorReplace/M0/cpct_spriteColorizeM0_asmbindings.s b/cpctelera/src/sprites/colorReplace/M0/cpct_spriteColorizeM0_asmbindings.s index 7e0c605f6..1362dbb6b 100644 --- a/cpctelera/src/sprites/colorReplace/M0/cpct_spriteColorizeM0_asmbindings.s +++ b/cpctelera/src/sprites/colorReplace/M0/cpct_spriteColorizeM0_asmbindings.s @@ -18,19 +18,19 @@ ;;------------------------------------------------------------------------------- .module cpct_sprites -.include "macros/cpct_undocumentedOpcodes.h.s" +.include "../macros/cpct_undocumentedOpcodes.s" ;; ;; ASM bindings for <cpct_spriteColorizeM0> ;; cpct_spriteColorizeM0_asm:: ;; Assembly entry point - ;; GET Parameters from the stack - ld (dms_restore_ix + 2), ix ;; [6] Save IX to restore it before returning - pop hl ;; [3] HL = Return Address + ;; GET Parameters from the stack + ld (dms_restore_ix + 2), ix ;; [6] Save IX to restore it before returning .include /cpct_spriteColorizeM0.asm/ dms_restore_ix: ld ix, #0000 ;; [4] Restore IX before returning - ret ;; [3] Return to caller \ No newline at end of file + ret ;; [3] Return to caller + diff --git a/cpctelera/src/sprites/colorReplace/M0/cpct_spriteColorizeM0_cbindings.s b/cpctelera/src/sprites/colorReplace/M0/cpct_spriteColorizeM0_cbindings.s index 55fb9fa68..4d67122d8 100644 --- a/cpctelera/src/sprites/colorReplace/M0/cpct_spriteColorizeM0_cbindings.s +++ b/cpctelera/src/sprites/colorReplace/M0/cpct_spriteColorizeM0_cbindings.s @@ -18,7 +18,7 @@ ;;------------------------------------------------------------------------------- .module cpct_sprites -.include "macros/cpct_undocumentedOpcodes.h.s" +.include "../macros/cpct_undocumentedOpcodes.s" ;; ;; C bindings for <cpct_spriteColorizeM0> @@ -29,20 +29,19 @@ _cpct_spriteColorizeM0:: ;; GET Parameters from the stack ld (dms_restore_ix + 2), ix ;; [6] Save IX to restore it before returning - pop hl ;; [3] HL = Return Address + pop de ;; [3] DE = Return Address - exx + exx ;; [1] Swap to alternate registers pop hl ;; [3] HL' = Source address (Sprite) pop de ;; [3] DE' = Destination Sprite color pop bc ;; [5] BC' = (B = Sprite Height, C = Width) - exx + exx ;; [1] Swap to default registers - ex (sp), hl ;; [6] HL = (H = newColor, L = oldColor) - ;; ... and leave Return Address at (SP) as we don't need to restore - ;; ... stack status because callin convention is __z88dk_callee + push de ;; [4] Put returning address in the stack again + ;; as this function uses __z88dk_callee convention .include /cpct_spriteColorizeM0.asm/ dms_restore_ix: ld ix, #0000 ;; [4] Restore IX before returning - ret ;; [3] Return to caller \ No newline at end of file + ret ;; [3] Return to caller diff --git a/cpctelera/src/sprites/colorReplace/M0/cpct_spriteMaskedColorizeM0.asm b/cpctelera/src/sprites/colorReplace/M0/cpct_spriteMaskedColorizeM0.asm index 37a32f02e..6ebf9798b 100644 --- a/cpctelera/src/sprites/colorReplace/M0/cpct_spriteMaskedColorizeM0.asm +++ b/cpctelera/src/sprites/colorReplace/M0/cpct_spriteMaskedColorizeM0.asm @@ -1,6 +1,6 @@ ;;-----------------------------LICENSE NOTICE------------------------------------ ;; This file is part of CPCtelera: An Amstrad CPC Game Engine -;; Copyright (C) 2018 Arnaud Bouche (@Arnaud6128) +;; Copyright (C) 2018 Arnaud Bouche (@Arnaud6128)) ;; Copyright (C) 2018 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) ;; ;; This program is free software: you can redistribute it and/or modify @@ -25,15 +25,13 @@ ;; Replace a color in a Masked sprite and copy to another or the same sprite. ;; ;; C Definition: -;; void <cpct_spriteMaskedColorizeM0> (void* *sprite*, void* *spriteColor*, <u8> *width*, <u8> *height*, <u8> *oldColor*, <u8> *newColor*) __z88dk_callee; +;; void <cpct_spriteMaskedColorizeM0> (void* *sprite*, void* *spriteColor*, <u8> *width*, <u8> *height*) __z88dk_callee; ;; ;; Input Parameters (6 bytes): ;; (2B HL') sprite - Source Sprite Pointer (array of pixel data) ;; (2B DE') spriteColor - Destination Sprite Pointer (can be also the Source Sprite) (array of pixel data) ;; (1B C') height - Sprite Height in bytes (>0) ;; (1B B') width - Sprite Width in *bytes* (Beware, *not* in pixels!) -;; (1B L) oldColor - Color to replace -;; (1B H) newColor - New color ;; ;; Assembly call (Input parameters on registers): ;; > call cpct_spriteMaskedColorizeM0_asm @@ -57,19 +55,17 @@ ;; There is no practical upper limit to this value. Height of a sprite in ;; bytes and pixels is the same value, as bytes only group consecutive pixels in ;; the horizontal space. -;; * *oldColor* must be the index of color (0 to 15) to replace -;; * *newColor* must be the index of the new color (0 to 15) ;; ;; Known limitations: ;; * This function *will not work from ROM*, as it uses self-modifying code. ;; * This function requires the CPC firmware to be DISABLED. Otherwise, random crashes might happen due to side effects. ;; ;; Destroyed Register values: -;; AF, BC, DE, HL, BC', DE', HL', IX +;; AF, BC, DE, BC', DE', HL', IX ;; ;; Required memory: -;; C-bindings - 87 bytes -;; ASM-bindings - 73 bytes +;; C-bindings - 165 bytes +;; ASM-bindings - 160 bytes ;; ;; Time Measures: ;; (start code) @@ -92,35 +88,19 @@ ;; Thanks to all of them for their help and support. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -.globl dc_mode0_ct +.globl _cpct_color_old +.globl _cpct_color_new -;; Macro to convert Pixel to xAxC xBxD format -.macro convertPixel - ;; From cpct_px2byteM0 - ld bc, #dc_mode0_ct ;; [3] BC points to conversion table (dc_mode0_ct) - - ;; Compute BC += A - add c ;; [1] | C += A - ld c, a ;; [1] | - sub a ;; [1] A = 0 (preserving Carry Flag) - adc b ;; [1] | B += Carry - ld b, a ;; [1] | - - ;; A = *(BC + A) - ld a, (bc) ;; [2] A = Value stored at the table pointed by BC -.endm - - ;; Convert newColor to pixel format (E) - ld a, h ;; [1] A = H new color index - convertPixel ;; [10] | Convert into A + ;; newColor to pixel format (E) + ld a, (_cpct_color_new);; [4] A = mem new color index ld e, a ;; [1] | E = A new color : xAxC xBxD - ;; Convert oldColor to pixel format (D) - ld a, l ;; [1] A = L old color index - convertPixel ;; [10] | Convert into A + ;; oldColor to pixel format (D) + ld a, (_cpct_color_old);; [4] A = mem old color index ld d, a ;; [1] | D = A old color : xAxC xBxD ld c, #0x55 ;; [2] C = Mask to get pixel A : xAxC xBxD + exx ;; [1] Switch to Alternate registers ld__ixl_c ;; [1] IXL = C (Width) @@ -168,8 +148,8 @@ setByte: inc de ;; [2] Next byte sprite colorized djnz lineLoop ;; [3] Decrement B (Width) if != 0 goto lineLoop - dec c ;; [1] Decrement C (Height) - jr nz, convertLoop ;; [2/3] If C == O goto end + dec c ;; [1] Decrement C (Height) + jr nz, convertLoop ;; [2/3] If C == O goto end end: ;; Return is included in bindings \ No newline at end of file diff --git a/cpctelera/src/sprites/colorReplace/M0/cpct_spriteMaskedColorizeM0_asmbindings.s b/cpctelera/src/sprites/colorReplace/M0/cpct_spriteMaskedColorizeM0_asmbindings.s index c95fedf88..af949e8a6 100644 --- a/cpctelera/src/sprites/colorReplace/M0/cpct_spriteMaskedColorizeM0_asmbindings.s +++ b/cpctelera/src/sprites/colorReplace/M0/cpct_spriteMaskedColorizeM0_asmbindings.s @@ -1,6 +1,6 @@ ;;-----------------------------LICENSE NOTICE------------------------------------ ;; This file is part of CPCtelera: An Amstrad CPC Game Engine -;; Copyright (C) 2018 Arnaud Bouche (@Arnaud6128) +;; Copyright (C) 2018 Arnaud Bouche (Arnaud6128) ;; Copyright (C) 2018 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) ;; ;; This program is free software: you can redistribute it and/or modify @@ -18,7 +18,7 @@ ;;------------------------------------------------------------------------------- .module cpct_sprites -.include "macros/cpct_undocumentedOpcodes.h.s" +.include "../macros/cpct_undocumentedOpcodes.s" ;; ;; ASM bindings for <cpct_spriteMaskedColorizeM0> @@ -27,7 +27,6 @@ cpct_spriteMaskedColorizeM0_asm:: ;; Assembly entry point ;; GET Parameters from the stack ld (dms_restore_ix + 2), ix ;; [6] Save IX to restore it before returning - pop hl ;; [3] HL = Return Address .include /cpct_spriteMaskedColorizeM0.asm/ diff --git a/cpctelera/src/sprites/colorReplace/M0/cpct_spriteMaskedColorizeM0_cbindings.s b/cpctelera/src/sprites/colorReplace/M0/cpct_spriteMaskedColorizeM0_cbindings.s index 0d7b9088d..c74a0ea07 100644 --- a/cpctelera/src/sprites/colorReplace/M0/cpct_spriteMaskedColorizeM0_cbindings.s +++ b/cpctelera/src/sprites/colorReplace/M0/cpct_spriteMaskedColorizeM0_cbindings.s @@ -18,7 +18,7 @@ ;;------------------------------------------------------------------------------- .module cpct_sprites -.include "macros/cpct_undocumentedOpcodes.h.s" +.include "../macros/cpct_undocumentedOpcodes.s" ;; ;; C bindings for <cpct_spriteMaskedColorizeM0> @@ -29,7 +29,7 @@ _cpct_spriteMaskedColorizeM0:: ;; GET Parameters from the stack ld (dms_restore_ix + 2), ix ;; [6] Save IX to restore it before returning - pop hl ;; [3] HL = Return Address + pop de ;; [3] DE = Return Address exx pop hl ;; [3] HL' = Source address (Sprite) @@ -37,9 +37,8 @@ _cpct_spriteMaskedColorizeM0:: pop bc ;; [5] BC' = (B = Sprite Height, C = Width) exx - ex (sp), hl ;; [6] HL = (H = newColor, L = oldColor) - ;; ... and leave Return Address at (SP) as we don't need to restore - ;; ... stack status because callin convention is __z88dk_callee + push de ;; [4] Put returning address in the stack again + ;; as this function uses __z88dk_callee convention .include /cpct_spriteMaskedColorizeM0.asm/ diff --git a/cpctelera/src/sprites/colorReplace/colorReplace.h b/cpctelera/src/sprites/colorReplace/colorReplace.h index a1e70b731..79cc0f19a 100644 --- a/cpctelera/src/sprites/colorReplace/colorReplace.h +++ b/cpctelera/src/sprites/colorReplace/colorReplace.h @@ -28,20 +28,20 @@ #ifndef CPCT_COLORREPLACE_H #define CPCT_COLORREPLACE_H -extern void cpct_setSpriteColourizeM0_f(u8 oldColour, u8 newColour) __z88dk_callee; -extern void cpct_spriteColourizeM0_f(u8 width, u8 height, u8 *sprite) __z88dk_callee; +// Function to set colors to replace M0 +extern void cpct_setReplaceColorsM0(u8 oldColor, u8 newColor) __z88dk_callee; // Functions to replace a color in sprite M0 -extern void cpct_spriteColorizeM0(u8* sprite, u8* spriteColor, u8 width, u8 height, u8 oldColor, u8 newColor) __z88dk_callee; -extern void cpct_spriteMaskedColorizeM0(u8* sprite, u8* spriteColor, u8 width, u8 height, u8 oldColor, u8 newColor) __z88dk_callee; +extern void cpct_spriteColorizeM0(u8* sprite, u8* spriteColor, u8 width, u8 height) __z88dk_callee; +extern void cpct_spriteMaskedColorizeM0(u8* sprite, u8* spriteColor, u8 width, u8 height) __z88dk_callee; // Functions to draw a sprite M0 with a color replaced -extern void cpct_drawSpriteColorizeM0(u8* sprite, u8* destMem, u8 width, u8 height, u8 oldColor, u8 newColor) __z88dk_callee; -extern void cpct_drawSpriteMaskedColorizeM0(u8* sprite, u8* destMem, u8 width, u8 height, u8 oldColor, u8 newColor) __z88dk_callee; -extern void cpct_drawSpriteMaskedAlignedColorizeM0(u8* sprite, u8* destMem, u8 width, u8 height, u8 oldColor, u8 newColor, const u8* maskTable) __z88dk_callee; +extern void cpct_drawSpriteColorizeM0(u8* sprite, u8* destMem, u8 width, u8 height) __z88dk_callee; +extern void cpct_drawSpriteMaskedColorizeM0(u8* sprite, u8* destMem, u8 width, u8 height) __z88dk_callee; +extern void cpct_drawSpriteMaskedAlignedColorizeM0(u8* sprite, u8* destMem, u8 width, u8 height, const u8* maskTable) __z88dk_callee; // Functions to replace a color in sprite M1 -extern void cpct_spriteColorizeM1(u8* sprite, u8* spriteColor, u8 width, u8 height, u8 oldColor, u8 newColor) __z88dk_callee; +extern void cpct_spriteColorizeM1(u8* sprite, u8* spriteColor, u8 width, u8 height) __z88dk_callee; extern void cpct_spriteMaskedColorizeM1(u8* sprite, u8* spriteColor, u8 width, u8 height, u8 oldColor, u8 newColor) __z88dk_callee; // Functions to draw a sprite M1 with a color replaced diff --git a/examples/medium/colorReplace/src/drawing.c b/examples/medium/colorReplace/src/drawing.c index 4cf6a249d..aa02f4f8a 100644 --- a/examples/medium/colorReplace/src/drawing.c +++ b/examples/medium/colorReplace/src/drawing.c @@ -1,8 +1,8 @@ //-----------------------------LICENSE NOTICE------------------------------------ // This file is part of CPCtelera: An Amstrad CPC Game Engine -// Copyright (C) 2018 Bouche Arnaud (@Arnaud6128) -// Copyright (C) 2018 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) +// Copyright (C) 2017 Bouche Arnaud +// Copyright (C) 2017 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Lesser General Public License as published by @@ -22,109 +22,107 @@ ///////////////////////////////////////////////////////////////////////////////// // GLOBAL VARIABLES -u8 gSpriteColorized[G_BALOON_W*G_BALOON_H]; // Array for sprite to color -u8 gBackGroundColor; // Background color -u8 gBaloonColor; // Current color baloon -u8 gPosCloud; // Position of cloude +u8 gSpriteColorized[G_BALOON_W*G_BALOON_H]; // Array for sprite to color +u8 gBackGroundColor; // Background color +u8 gBaloonColor; // Current color baloon +u8 gPosCloud; // Position of cloude ///////////////////////////////////////////////////////////////////////////////// // STRUCTURES DEFINITION -typedef struct TBaloon // Baloon structure +typedef struct TBaloon // Baloon structure { - i16 posY; // Absolute Baloon PosY (can be outside screen) - u8 posX; // Absolute Baloon PosX - - u8 drawPosY; // In screen Baloon PosY - u8 drawCY; // In screen Baloon Height - - u8 speed; // Baloon speed - u8 color; // Baloon color drawn - - u8 status; // Baloon status ACTIVE / INACTIVE + i16 posY; // Absolute Baloon PosY (can be outside screen) + u8 posX; // Absolute Baloon PosX + + u8 drawPosY; // In screen Baloon PosY + u8 drawCY; // In screen Baloon Height + + u8 speed; // Baloon speed + u8 color; // Baloon color drawn + + u8 status; // Baloon status ACTIVE / INACTIVE } SBaloon; -typedef struct TBaloons // All baloons structure +typedef struct TBaloons // All baloons structure { - u8 nb; // Nb baloons in screen - SBaloon baloons[NB_BALOONS]; // Array of baloon + u8 nb; // Nb baloons in screen + SBaloon baloons[NB_BALOONS]; // Array of baloon } SBaloons; -SBaloons gBaloons; // Baloons to draw +SBaloons gBaloons; // Baloons to draw -typedef struct TStar // Lighting star structure +typedef struct TStar // Lighting star structure { - u8 posX; // Screen PosX - u8 posY; // Screen PosY + u8 posX; // Screen PosX + u8 posY; // Screen PosY - u8 color; // Star color drawn + u8 color; // Star color drawn } SStar; -typedef struct TStars // All stars structure +typedef struct TStars // All stars structure { - SStar stars[NB_STARS]; // Array of stars + SStar stars[NB_STARS]; // Array of stars } SStars; -SStars gStars; // Stars to draw +SStars gStars; // Stars to draw /////////////////////////////////////////////////////// -/// GET RANDOM FROM 0 TO MAX-1 +/// GET RANDOM FROM 0 TO MAX-1 /// u8 GetRand(u8 max) { - return cpct_rand()%max; + return cpct_rand()%max; } /////////////////////////////////////////////////////// -/// CHANGE TWO COLORS OF BALOON SPRITE +/// CHANGE TWO COLORS OF BALOON SPRITE /// void ColorSprite(u8 color) { - // Replace the two colors 1 and 2 of sprite baloon - //cpct_spriteColorizeM0(g_baloon, gSpriteColorized, G_BALOON_W, G_BALOON_H, 1, color); // Colors are consecutives - //cpct_spriteColorizeM0(gSpriteColorized, gSpriteColorized, G_BALOON_W, G_BALOON_H, 2, color + 1); - cpct_memcpy(gSpriteColorized, g_baloon, G_BALOON_H*G_BALOON_W); - cpct_setSpriteColourizeM0_f(1, color); - cpct_spriteColourizeM0_f(G_BALOON_W, G_BALOON_H, gSpriteColorized); - cpct_setSpriteColourizeM0_f(2, color + 1); - cpct_spriteColourizeM0_f(G_BALOON_W, G_BALOON_H, gSpriteColorized); + // Replace the two colors 1 and 2 of sprite baloon + cpct_setReplaceColorsM0(1, color); + cpct_spriteColorizeM0(g_baloon, gSpriteColorized, G_BALOON_W, G_BALOON_H); // Colors are consecutives + + cpct_setReplaceColorsM0(2, color + 1); + cpct_spriteColorizeM0(gSpriteColorized, gSpriteColorized, G_BALOON_W, G_BALOON_H); } /////////////////////////////////////////////////////// -/// CLEAR BALOON BACKGROUND +/// CLEAR BALOON BACKGROUND /// void ClearBaloon(SBaloon* baloon) { - // If baloon in visible part of view - if (baloon->drawPosY < VIEW_DOWN) - { - u8* pvmem; - - // Compute size to be filled with background color - u8 clearCY = baloon->drawCY + BALOON_TRAIL; - - // Compute position to clear - u8 posDownClearY = baloon->drawPosY + clearCY; - if (posDownClearY > VIEW_DOWN) - clearCY = VIEW_DOWN - baloon->drawPosY; - - // Draw the box with background color to clear - pvmem = GetBackBufferPtr(baloon->posX, baloon->drawPosY); - cpct_drawSolidBox(pvmem, gBackGroundColor, G_BALOON_W, clearCY); - } + // If baloon in visible part of view + if (baloon->drawPosY < VIEW_DOWN) + { + u8* pvmem; + + // Compute size to be filled with background color + u8 clearCY = baloon->drawCY + BALOON_TRAIL; + + // Compute position to clear + u8 posDownClearY = baloon->drawPosY + clearCY; + if (posDownClearY > VIEW_DOWN) + clearCY = VIEW_DOWN - baloon->drawPosY; + + // Draw the box with background color to clear + pvmem = GetBackBufferPtr(baloon->posX, baloon->drawPosY); + cpct_drawSolidBox(pvmem, gBackGroundColor, G_BALOON_W, clearCY); + } } /////////////////////////////////////////////////////// -/// DELETE BALOON +/// DELETE BALOON /// void DeleteBaloons(SBaloon* baloons, SBaloon* baloonToDel, u8* nb) { - // Get last baloon in array - // Decrement number of remaining baloons in array - const SBaloon* lastBaloon = &baloons[--*nb]; - - // Replace baloon to be deleted with last baloon (if they are not the same) - if (baloonToDel != lastBaloon) - cpct_memcpy(baloonToDel, lastBaloon, sizeof(SBaloon)); + // Get last baloon in array + // Decrement number of remaining baloons in array + const SBaloon* lastBaloon = &baloons[--*nb]; + + // Replace baloon to be deleted with last baloon (if they are not the same) + if (baloonToDel != lastBaloon) + cpct_memcpy(baloonToDel, lastBaloon, sizeof(SBaloon)); } /////////////////////////////////////////////////////// @@ -132,85 +130,85 @@ void DeleteBaloons(SBaloon* baloons, SBaloon* baloonToDel, u8* nb) /// void UpdateBaloons() { - SBaloon* itBaloon = gBaloons.baloons; - u8 i; - - // Test if we can add a new baloon - if (gBaloons.nb < NB_BALOONS) - { - // Add new baloon at end of array - // Increment number of baloons in array - SBaloon* newBaloon = &gBaloons.baloons[gBaloons.nb++]; - - // Get random positions X and Y - newBaloon->posX = GetRand(SCREEN_CX - G_BALOON_W); - newBaloon->posY = SCREEN_CY - GetRand(40); - - // Get random speed - newBaloon->speed = GetRand(3) + 2; - - // Get circular next color 2 by 2 until 12 - gBaloonColor = (gBaloonColor + 2) % 12; - newBaloon->color = gBaloonColor + 1; - - // Set baloon ACTIVE - newBaloon->status = BALOON_ACTIVE; - } - - // Update all baloons - for (i = 0; i < gBaloons.nb; i++) - { - // If baloon active move and draw it - if (itBaloon->status == BALOON_ACTIVE) - { - // Test if whole baloon outside view - if (itBaloon->posY + G_BALOON_H < VIEW_TOP) - { - // Set baloon inactive - itBaloon->status = BALOON_INACTIVE; - // Clear baloon background - ClearBaloon(itBaloon); - } - else - { - // Move baloon to up according its speed - i16 posY = itBaloon->posY - itBaloon->speed; - itBaloon->posY = posY; + SBaloon* itBaloon = gBaloons.baloons; + u8 i; + + // Test if we can add a new baloon + if (gBaloons.nb < NB_BALOONS) + { + // Add new baloon at end of array + // Increment number of baloons in array + SBaloon* newBaloon = &gBaloons.baloons[gBaloons.nb++]; + + // Get random positions X and Y + newBaloon->posX = GetRand(SCREEN_CX - G_BALOON_W); + newBaloon->posY = SCREEN_CY - GetRand(40); + + // Get random speed + newBaloon->speed = GetRand(3) + 2; + + // Get circular next color 2 by 2 until 12 + gBaloonColor = (gBaloonColor + 2) % 12; + newBaloon->color = gBaloonColor + 1; + + // Set baloon ACTIVE + newBaloon->status = BALOON_ACTIVE; + } + + // Update all baloons + for (i = 0; i < gBaloons.nb; i++) + { + // If baloon active move and draw it + if (itBaloon->status == BALOON_ACTIVE) + { + // Test if whole baloon outside view + if (itBaloon->posY + G_BALOON_H < VIEW_TOP) + { + // Set baloon inactive + itBaloon->status = BALOON_INACTIVE; + // Clear baloon background + ClearBaloon(itBaloon); + } + else + { + // Move baloon to up according its speed + i16 posY = itBaloon->posY - itBaloon->speed; + itBaloon->posY = posY; - // Baloon outside view by top - if (posY < VIEW_TOP) - { - itBaloon->drawPosY = 0; - itBaloon->drawCY = G_BALOON_H + posY; - } - else - // Baloon outside view by down - if (posY + G_BALOON_H > VIEW_DOWN) - { - itBaloon->drawPosY = posY; - itBaloon->drawCY = VIEW_DOWN - posY; - } - // Baloon all in view - else - { - itBaloon->drawPosY = posY; - itBaloon->drawCY = G_BALOON_H; - } - } - } - // If inactive delete baloon - else - { - // Clear baloon background - ClearBaloon(itBaloon); - - // Delete baloon from list - DeleteBaloons(gBaloons.baloons, itBaloon, &gBaloons.nb); - } - - // Get next baloon pointer - itBaloon++; - } + // Baloon outside view by top + if (posY < VIEW_TOP) + { + itBaloon->drawPosY = 0; + itBaloon->drawCY = G_BALOON_H + posY; + } + else + // Baloon outside view by down + if (posY + G_BALOON_H > VIEW_DOWN) + { + itBaloon->drawPosY = posY; + itBaloon->drawCY = VIEW_DOWN - posY; + } + // Baloon all in view + else + { + itBaloon->drawPosY = posY; + itBaloon->drawCY = G_BALOON_H; + } + } + } + // If inactive delete baloon + else + { + // Clear baloon background + ClearBaloon(itBaloon); + + // Delete baloon from list + DeleteBaloons(gBaloons.baloons, itBaloon, &gBaloons.nb); + } + + // Get next baloon pointer + itBaloon++; + } } /////////////////////////////////////////////////////// @@ -218,27 +216,27 @@ void UpdateBaloons() /// void DrawBaloon(SBaloon* baloon, const u8* spriteBaloon) { - i16 posY = baloon->posY; - - // If baloon in view - if (posY + G_BALOON_H > VIEW_TOP && posY < VIEW_DOWN) - { - // Get VMem pointer of current baloon position - u8* pvmem = GetBackBufferPtr(baloon->posX, baloon->drawPosY); - const u8* sprite = (u8*)spriteBaloon; - - // Baloon partialy outside view by top - if (posY < VIEW_TOP) - { - // Compute Y position - u8 y = -posY; - - // Compute sprite offset - sprite = (u8*)spriteBaloon + G_BALOON_W * y; - } - - cpct_drawSpriteMaskedAlignedTable(sprite, pvmem, G_BALOON_W, baloon->drawCY, gMaskTable); - } + i16 posY = baloon->posY; + + // If baloon in view + if (posY + G_BALOON_H > VIEW_TOP && posY < VIEW_DOWN) + { + // Get VMem pointer of current baloon position + u8* pvmem = GetBackBufferPtr(baloon->posX, baloon->drawPosY); + const u8* sprite = (u8*)spriteBaloon; + + // Baloon partialy outside view by top + if (posY < VIEW_TOP) + { + // Compute Y position + u8 y = -posY; + + // Compute sprite offset + sprite = (u8*)spriteBaloon + G_BALOON_W * y; + } + + cpct_drawSpriteMaskedAlignedTable(sprite, pvmem, G_BALOON_W, baloon->drawCY, gMaskTable); + } } /////////////////////////////////////////////////////// @@ -246,42 +244,45 @@ void DrawBaloon(SBaloon* baloon, const u8* spriteBaloon) /// void DrawStars() { - // Static stars color - const static u8 sColorStar[NB_COLORS_STAR] = { 2, 4, 7, 8, 10, 11, 12 }; - static u8 color = 0; - - u8 i; - for (i = 0; i < NB_STARS; i++) - { - // Get video pointer of each star to be drawn - u8* pvmem = GetBackBufferPtr(gStars.stars[i].posX, gStars.stars[i].posY); - u8 color = gStars.stars[i].color++; - - // Use different drawing color methods - if (i < NB_STARS/3) - { - // Color and draw masked sprite in video memory - cpct_drawSpriteMaskedColorizeM0(g_star_trans, pvmem, G_STAR_TRANS_W, G_STAR_TRANS_H, 15, sColorStar[color]); - } - else if (i > NB_STARS/3 && i < 2*NB_STARS/3) - { - // Color and draw masked aligned sprite in video memory - cpct_drawSpriteMaskedAlignedColorizeM0(g_square, pvmem, G_SQUARE_W, G_SQUARE_H, 15, sColorStar[color], gMaskTable); - } - else - { - // Color and copy masked sprite in temporary array - u8 circleColor[G_CIRCLE_TRANS_W * G_CIRCLE_TRANS_H * 2]; - cpct_spriteMaskedColorizeM0(g_circle_trans, circleColor, G_CIRCLE_TRANS_W, G_CIRCLE_TRANS_H, 15, sColorStar[color]); - - // Draw masked Sprite from temporary array - cpct_drawSpriteMasked(circleColor, pvmem, G_CIRCLE_TRANS_W, G_CIRCLE_TRANS_H); - } - - // If all colors palette used restart from 0 - if (color == NB_COLORS_STAR - 1) - gStars.stars[i].color = 0; - } + // Static stars color + const static u8 sColorStar[NB_COLORS_STAR] = { 2, 4, 7, 8, 10, 11, 12 }; + static u8 color = 0; + + u8 i; + for (i = 0; i < NB_STARS; i++) + { + // Get video pointer of each star to be drawn + u8* pvmem = GetBackBufferPtr(gStars.stars[i].posX, gStars.stars[i].posY); + u8 color = gStars.stars[i].color++; + + // Set color to change + cpct_setReplaceColorsM0(15, sColorStar[color]); + + // Use different drawing color methods + if (i < NB_STARS/3) + { + // Color and draw masked sprite in video memory + cpct_drawSpriteMaskedColorizeM0(g_star_trans, pvmem, G_STAR_TRANS_W, G_STAR_TRANS_H); + } + else if (i > NB_STARS/3 && i < 2*NB_STARS/3) + { + // Color and draw masked aligned sprite in video memory + cpct_drawSpriteMaskedAlignedColorizeM0(g_square, pvmem, G_SQUARE_W, G_SQUARE_H, gMaskTable); + } + else + { + // Color and copy masked sprite in temporary array + u8 circleColor[G_CIRCLE_TRANS_W * G_CIRCLE_TRANS_H * 2]; + cpct_spriteMaskedColorizeM0(g_circle_trans, circleColor, G_CIRCLE_TRANS_W, G_CIRCLE_TRANS_H); + + // Draw masked Sprite from temporary array + cpct_drawSpriteMasked(circleColor, pvmem, G_CIRCLE_TRANS_W, G_CIRCLE_TRANS_H); + } + + // If all colors palette used restart from 0 + if (color == NB_COLORS_STAR - 1) + gStars.stars[i].color = 0; + } } /////////////////////////////////////////////////////// @@ -289,9 +290,9 @@ void DrawStars() /// void DrawCloud() { - // Draw cloud at fixed place - u8* pvmem = GetBackBufferPtr(0, POS_CLOUD_Y); - cpct_drawSprite(g_cloud, pvmem, G_CLOUD_W, G_CLOUD_H); + // Draw cloud at fixed place + u8* pvmem = GetBackBufferPtr(0, POS_CLOUD_Y); + cpct_drawSprite(g_cloud, pvmem, G_CLOUD_W, G_CLOUD_H); } /////////////////////////////////////////////////////// @@ -299,35 +300,40 @@ void DrawCloud() /// void DrawSceneBaloons() { - u8 i; - - // Clear background for all baloons - SBaloon* itBaloon = gBaloons.baloons; // Get first baloon pointer - for (i = 0; i < gBaloons.nb; i++) - { - ClearBaloon(itBaloon); - itBaloon++; - } - - // Draw sprite cloud - DrawCloud(); - - // Draw all baloons - itBaloon = gBaloons.baloons; // Get first baloon pointer - for (i = 0; i < gBaloons.nb; i++) - { - const u8* sprite = g_baloon; // Default baloon sprite (blue) + u8 i, color = 0; + + // Clear background for all baloons + SBaloon* itBaloon = gBaloons.baloons; // Get first baloon pointer + for (i = 0; i < gBaloons.nb; i++) + { + ClearBaloon(itBaloon); + itBaloon++; + } + + // Draw sprite cloud + DrawCloud(); + + // Draw all baloons + itBaloon = gBaloons.baloons; // Get first baloon pointer + for (i = 0; i < gBaloons.nb; i++) + { + const u8* sprite = g_baloon; // Default baloon sprite (blue) - // Test if sprite have colors to change - if (itBaloon->color > 1) // Color 0 (white) is transparent color - { - ColorSprite(itBaloon->color); // Change colors of ballon - sprite = gSpriteColorized; // Sprite to draw is colorized baloon - } - - DrawBaloon(itBaloon, sprite); // Draw baloon sprite - itBaloon++; // Get next baloon - } + // Test if sprite have colors to change + if (itBaloon->color > 1) // Color 0 (white) is transparent color + { + if (color != itBaloon->color) // Test if need to change Color of Sprite + { + color = itBaloon->color; + ColorSprite(color); // Change colors of ballon + } + + sprite = gSpriteColorized; // Sprite to draw is colorized baloon + } + + DrawBaloon(itBaloon, sprite); // Draw baloon sprite + itBaloon++; // Get next baloon + } } /////////////////////////////////////////////////////// @@ -335,21 +341,21 @@ void DrawSceneBaloons() /// void DrawBackground() { - u8* pvmem; - - // Fill video buffer with background color - cpct_memset((u8*)SCREEN_BUFF, gBackGroundColor, VMEM_SIZE); - - // Draw left part of Roof - pvmem = GetBackBufferPtr(0, SCREEN_CY-G_ROOF_H); - cpct_drawSprite(g_roof, pvmem, G_ROOF_W, G_ROOF_H); - - // Draw right part of Roof - pvmem += G_ROOF_W; - cpct_drawSprite(g_roof, pvmem, G_ROOF_W, G_ROOF_H); - - // Copy Same background on both buffers - cpct_memcpy(CPCT_VMEM_START, (u8*)SCREEN_BUFF, VMEM_SIZE); + u8* pvmem; + + // Fill video buffer with background color + cpct_memset((u8*)SCREEN_BUFF, gBackGroundColor, VMEM_SIZE); + + // Draw left part of Roof + pvmem = GetBackBufferPtr(0, SCREEN_CY-G_ROOF_H); + cpct_drawSprite(g_roof, pvmem, G_ROOF_W, G_ROOF_H); + + // Draw right part of Roof + pvmem += G_ROOF_W; + cpct_drawSprite(g_roof, pvmem, G_ROOF_W, G_ROOF_H); + + // Copy Same background on both buffers + cpct_memcpy(CPCT_VMEM_START, (u8*)SCREEN_BUFF, VMEM_SIZE); } ///////////////////////////////////////////////////////////////////////////////// @@ -359,18 +365,18 @@ void DrawBackground() /// void InitializeDrawing() { - u8 dx = SCREEN_CX / NB_STARS; // Compute space between stars - - u8 i; - for (i = 0; i < NB_STARS; i++) - { - gStars.stars[i].posX = dx * i + 5; // Constant space beetween stars - gStars.stars[i].posY = GetRand(10) + 175; // Random Y position from 175 to 184 - gStars.stars[i].color = GetRand(NB_COLORS_STAR); // Random color from 0 to NB_COLORS_STAR-1 - } - - gBackGroundColor = cpct_px2byteM0(14, 14); // Get byte color of background for M0 - gBaloons.nb = 0; // No baloon to draw at start - - DrawBackground(); // Set background on both buffers + u8 dx = SCREEN_CX / NB_STARS; // Compute space between stars + + u8 i; + for (i = 0; i < NB_STARS; i++) + { + gStars.stars[i].posX = dx * i + 5; // Constant space beetween stars + gStars.stars[i].posY = GetRand(10) + 175; // Random Y position from 175 to 184 + gStars.stars[i].color = GetRand(NB_COLORS_STAR); // Random color from 0 to NB_COLORS_STAR-1 + } + + gBackGroundColor = cpct_px2byteM0(14, 14); // Get byte color of background for M0 + gBaloons.nb = 0; // No baloon to draw at start + + DrawBackground(); // Set background on both buffers } From 18582c467f6db9ae83b90b9097f89ae882c36b2b Mon Sep 17 00:00:00 2001 From: Arnaud <arnaud_bouche@hotmail.com> Date: Sat, 27 Jan 2018 10:20:53 +0100 Subject: [PATCH 31/31] Revert "Add new function cpct_setReplaceColors and update others" This reverts commit 04a34248f2969c862be31b1ed0941bf7a2d430a7. --- .../M0/cpct_drawSpriteColorizeM0.asm | 41 +- .../cpct_drawSpriteColorizeM0_asmbindings.s | 7 +- .../M0/cpct_drawSpriteColorizeM0_cbindings.s | 15 +- ...cpct_drawSpriteMaskedAlignedColorizeM0.asm | 149 ++--- ...priteMaskedAlignedColorizeM0_asmbindings.s | 7 +- ...wSpriteMaskedAlignedColorizeM0_cbindings.s | 17 +- .../M0/cpct_drawSpriteMaskedColorizeM0.asm | 56 +- ...t_drawSpriteMaskedColorizeM0_asmbindings.s | 3 +- ...pct_drawSpriteMaskedColorizeM0_cbindings.s | 11 +- .../colorReplace/M0/cpct_replaceColor.s | 44 -- .../M0/cpct_setReplaceColorsM0.asm | 87 --- .../M0/cpct_setReplaceColorsM0_cbinding.s | 31 -- .../colorReplace/M0/cpct_spriteColorizeM0.asm | 57 +- .../M0/cpct_spriteColorizeM0_asmbindings.s | 10 +- .../M0/cpct_spriteColorizeM0_cbindings.s | 15 +- .../M0/cpct_spriteMaskedColorizeM0.asm | 48 +- .../cpct_spriteMaskedColorizeM0_asmbindings.s | 5 +- .../cpct_spriteMaskedColorizeM0_cbindings.s | 9 +- .../src/sprites/colorReplace/colorReplace.h | 15 +- examples/medium/colorReplace/src/drawing.c | 521 +++++++++--------- 20 files changed, 542 insertions(+), 606 deletions(-) delete mode 100644 cpctelera/src/sprites/colorReplace/M0/cpct_replaceColor.s delete mode 100644 cpctelera/src/sprites/colorReplace/M0/cpct_setReplaceColorsM0.asm delete mode 100644 cpctelera/src/sprites/colorReplace/M0/cpct_setReplaceColorsM0_cbinding.s diff --git a/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteColorizeM0.asm b/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteColorizeM0.asm index 9ee49f27e..a40ef9e87 100644 --- a/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteColorizeM0.asm +++ b/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteColorizeM0.asm @@ -25,13 +25,15 @@ ;; Directly replace a color and draw a sprite to video memory. ;; ;; C Definition: -;; void <cpct_drawSpriteColorizeM0> (void* *sprite*, void* *memory*, <u8> *width*, <u8> *height*) __z88dk_callee; +;; void <cpct_drawSpriteColorizeM0> (void* *sprite*, void* *memory*, <u8> *width*, <u8> *height*, <u8> *oldColor*, <u8> *newColor*) __z88dk_callee; ;; ;; Input Parameters (8 bytes): ;; (2B HL') sprite - Source Sprite Pointer (array of pixel data) ;; (2B DE') memory - Destination video memory pointer ;; (1B C' ) height - Sprite Height in bytes (>0) ;; (1B B' ) width - Sprite Width in *bytes* (Beware, *not* in pixels!) +;; (1B L ) oldColor - Color to replace +;; (1B H ) newColor - New color ;; ;; Assembly call (Input parameters on registers): ;; > call cpct_drawSpriteColorizeM0_asm @@ -52,6 +54,8 @@ ;; There is no practical upper limit to this value. Height of a sprite in ;; bytes and pixels is the same value, as bytes only group consecutive pixels in ;; the horizontal space. +;; * *oldColor* must be the index of color (0 to 15) to replace +;; * *newColor* must be the index of the new color (0 to 15) ;; ;; Known limitations: ;; * This function does not do any kind of boundary check or clipping. If you @@ -72,8 +76,8 @@ ;; AF, BC, DE, HL, BC', DE', HL', IX ;; ;; Required memory: -;; C-bindings - 165 bytes -;; ASM-bindings - 160 bytes +;; C-bindings - 118 bytes +;; ASM-bindings - 108 bytes ;; ;; Time Measures: ;; (start code) @@ -96,15 +100,32 @@ ;; Thanks to all of them for their help and support. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -.globl _cpct_color_old -.globl _cpct_color_new +.globl dc_mode0_ct - ;; newColor to pixel format (E) - ld a, (_cpct_color_new);; [4] A = mem new color index +;; Macro to convert Pixel to xAxC xBxD format +.macro convertPixel + ;; From cpct_px2byteM0 + ld bc, #dc_mode0_ct ;; [3] BC points to conversion table (dc_mode0_ct) + + ;; Compute BC += A + add c ;; [1] | C += A + ld c, a ;; [1] | + sub a ;; [1] A = 0 (preserving Carry Flag) + adc b ;; [1] | B += Carry + ld b, a ;; [1] | + + ;; A = *(BC + A) + ld a, (bc) ;; [2] A = Value stored at the table pointed by BC +.endm + + ;; Convert newColor to pixel format (E) + ld a, h ;; [1] A = H new color index + convertPixel ;; [10] | Convert into A ld e, a ;; [1] | E = A new color : xAxC xBxD - ;; oldColor to pixel format (D) - ld a, (_cpct_color_old);; [4] A = mem old color index + ;; Convert oldColor to pixel format (D) + ld a, l ;; [1] A = L old color index + convertPixel ;; [10] | Convert into A ld d, a ;; [1] | D = A old color : xAxC xBxD ld c, #0x55 ;; [2] C = Mask to get pixel A : xAxC xBxD @@ -126,7 +147,7 @@ lineLoop: and c ;; [2] A |= C (C = 0x55) : xBxB xBxB cp d ;; [1] Test if pixel (A) is the old colour to be replaced (D) - jr nz, readPixelA ;; [2/3] If not equal go to next pixel + jr nz, readPixelA ;; [2/3] If not equal go to next pixel ld a, e ;; [1] else A = new colour to set (E) ;; Pixel Mode 0 = ABAB ABAB diff --git a/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteColorizeM0_asmbindings.s b/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteColorizeM0_asmbindings.s index 01bfcad7c..073609b70 100644 --- a/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteColorizeM0_asmbindings.s +++ b/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteColorizeM0_asmbindings.s @@ -1,7 +1,7 @@ ;;-----------------------------LICENSE NOTICE------------------------------------ ;; This file is part of CPCtelera: An Amstrad CPC Game Engine -;; Copyright (C) 2018 Arnaud Bouche (@Arnaud6128) -;; Copyright (C) 2018 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) +;; Copyright (C) 2017 Arnaud Bouche (@Arnaud6128) +;; Copyright (C) 2017 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) ;; ;; This program is free software: you can redistribute it and/or modify ;; it under the terms of the GNU Lesser General Public License as published by @@ -18,7 +18,7 @@ ;;------------------------------------------------------------------------------- .module cpct_sprites -.include "../macros/cpct_undocumentedOpcodes.s" +.include "../../../macros/cpct_undocumentedOpcodes.h.s" ;; ;; ASM bindings for <cpct_drawSpriteColorizeM0> @@ -27,6 +27,7 @@ cpct_drawSpriteColorizeM0_asm:: ;; Assembly entry point ;; GET Parameters from the stack ld (dms_restore_ix + 2), ix ;; [6] Save IX to restore it before returning + pop hl ;; [3] HL = Return Address ;;.include /cpct_drawSpriteColorizeM0.asm/ diff --git a/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteColorizeM0_cbindings.s b/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteColorizeM0_cbindings.s index 9b8ed88e2..f4ad4b2f5 100644 --- a/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteColorizeM0_cbindings.s +++ b/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteColorizeM0_cbindings.s @@ -1,7 +1,7 @@ ;;-----------------------------LICENSE NOTICE------------------------------------ ;; This file is part of CPCtelera: An Amstrad CPC Game Engine -;; Copyright (C) 2018 Arnaud Bouche (@Arnaud6128) -;; Copyright (C) 2018 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) +;; Copyright (C) 2017 Arnaud Bouche (@Arnaud6128) +;; Copyright (C) 2017 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) ;; ;; This program is free software: you can redistribute it and/or modify ;; it under the terms of the GNU Lesser General Public License as published by @@ -18,18 +18,18 @@ ;;------------------------------------------------------------------------------- .module cpct_sprites -.include "../macros/cpct_undocumentedOpcodes.s" +.include "../../../macros/cpct_undocumentedOpcodes.h.s" ;; ;; C bindings for <cpct_drawSpriteColorizeM0> ;; -;; 33 us, 8 bytes +;; 33 us, 10 bytes ;; _cpct_drawSpriteColorizeM0:: ;; GET Parameters from the stack ld (dms_restore_ix + 2), ix ;; [6] Save IX to restore it before returning - pop de ;; [3] DE = Return Address + pop hl ;; [3] HL = Return Address exx pop hl ;; [3] HL' = Source address (Sprite) @@ -37,8 +37,9 @@ _cpct_drawSpriteColorizeM0:: pop bc ;; [5] BC' = (B = Sprite Height, C = Width) exx - push de ;; [4] Put returning address in the stack again - ;; as this function uses __z88dk_callee convention + ex (sp), hl ;; [6] HL = (H = newColor, L = oldColor) + ;; ... and leave Return Address at (SP) as we don't need to restore + ;; ... stack status because callin convention is __z88dk_callee .include /cpct_drawSpriteColorizeM0.asm/ diff --git a/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteMaskedAlignedColorizeM0.asm b/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteMaskedAlignedColorizeM0.asm index a0dda77a4..981c21ab2 100644 --- a/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteMaskedAlignedColorizeM0.asm +++ b/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteMaskedAlignedColorizeM0.asm @@ -18,6 +18,8 @@ ;;------------------------------------------------------------------------------- .module cpct_sprites +.globl dc_mode0_ct + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; Function: cpct_drawSpriteMaskedAlignedColorizeM0 @@ -26,13 +28,15 @@ ;; ;; C Definition: ;; void <cpct_drawSpriteMaskedAlignedColorizeM0> (void* *sprite*, void* *memory*, <u8> *width*, <u8> *height*, -;; <u8*> *pmasktable*) __z88dk_callee; +;; <u8> *oldColor*, <u8> *newColor*, <u8*> *pmasktable*) __z88dk_callee; ;; -;; Input Parameters (8 bytes): +;; Input Parameters (10 bytes): ;; (2B HL') sprite - Source Sprite Pointer (array of pixel data) ;; (2B DE') memory - Destination video memory pointer ;; (1B C' ) height - Sprite Height in bytes (>0) ;; (1B B' ) width - Sprite Width in *bytes* (Beware, *not* in pixels!) +;; (1B E ) oldColor - Color to replace +;; (1B D ) newColor - New color ;; (2B HL) pmasktable - Pointer to the aligned mask table used to create transparency ;; ;; Assembly call (Input parameters on registers): @@ -54,6 +58,8 @@ ;; There is no practical upper limit to this value. Height of a sprite in ;; bytes and pixels is the same value, as bytes only group consecutive pixels in ;; the horizontal space. +;; * *oldColor* must be the index of color (0 to 15) to replace +;; * *newColor* must be the index of the new color (0 to 15) ;; ;; Known limitations: ;; * This function does not do any kind of boundary check or clipping. If you @@ -74,8 +80,8 @@ ;; AF, BC, DE, HL, BC', DE', HL', IX ;; ;; Required memory: -;; C-bindings - 165 bytes -;; ASM-bindings - 160 bytes +;; C-bindings - 112 bytes +;; ASM-bindings - 96 bytes ;; ;; Time Measures: ;; (start code) @@ -98,82 +104,97 @@ ;; Thanks to all of them for their help and support. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -.globl _cpct_color_old -.globl _cpct_color_new +;; Macro to convert Pixel to xAxC xBxD format +.macro convertPixel + ;; From cpct_px2byteM0 + ld bc, #dc_mode0_ct ;; [3] BC points to conversion table (dc_mode0_ct) + + ;; Compute BC += A + add c ;; [1] | C += A + ld c, a ;; [1] | + sub a ;; [1] A = 0 (preserving Carry Flag) + adc b ;; [1] | B += Carry + ld b, a ;; [1] | + + ;; A = *(BC + A) + ld a, (bc) ;; [2] A = Value stored at the table pointed by BC +.endm - ;; newColor to pixel format (E) - ld a, (_cpct_color_new);; [4] A = mem new color index + ;; Convert newColor to pixel format (E) + ld a, h ;; [1] A = H new color index + convertPixel ;; [10] | Convert into A ld e, a ;; [1] | E = A new color : xAxC xBxD - ;; oldColor to pixel format (D) - ld a, (_cpct_color_old);; [4] A = mem old color index - ld b, d ;; [1] B = D (Masked table adress High Byte) - ld d, a ;; [1] | D = A old color : xAxC xBxD - - ld c, #0x55 ;; [2] C = Mask to get pixel A : xAxC xBxD - exx ;; [1] Switch to Alternate registers - - ld__ixl_c ;; [1] IXL = C (Width) - ld c, b ;; [1] C = B (Height) - -convertLoop: - push de ;; [4] Store DE start line (DestMem) - ld__b_ixl ;; [2] B = IXL (Sprite Width) + ;; Convert oldColor to pixel format (D) + ld a, l ;; [1] A = L old color index + convertPixel ;; [10] | Convert into A + ld b, d + ld d, a ;; [1] | D = A old color : xAxC xBxD + + ld c, #0x55 ;; [2] C = Mask to get pixel A : xAxC xBxD + exx ;; [1] Switch to Alternate registers + + ld__ixl_c ;; [1] IXL = C (Width) + ld c, b ;; [1] C = B (Height) + +convertLoop: + push de ;; [4] Store DE start line (DestMem) + ld__b_ixl ;; [2] B = IXL (Sprite Width) lineLoop: - ld a, (hl) ;; [2] A = (HL) current Byte of sprite + ld a, (hl) ;; [2] A = (HL) current Byte of sprite exx ;; [1] Switch to Default registers - - ld l, a ;; [1] L = A current Byte of sprite : ABAB ABAB - and c ;; [2] A |= C (C = 0x55) : xBxB xBxB - - cp d ;; [1] Test if pixel (A) is the old colour to be replaced (D) - jr nz, readPixelA ;; [2/3] If not equal go to next pixel + + ld l, a ;; [1] L = A current Byte of sprite : ABAB ABAB + and c ;; [2] A |= C (C = 0x55) : xBxB xBxB + + cp d ;; [1] Test if pixel (A) is the old colour to be replaced (D) + jr nz, readPixelA ;; [2/3] If not equal go to next pixel ld a, e ;; [1] else A = new colour to set (E) ;; Pixel Mode 0 = ABAB ABAB readPixelA: - ld h, a ;; [1] H = A (current colorized sprite) : xBxB xBxB - ld a, l ;; [1] L = A current Byte of sprite : ABAB ABAB - rrca ;; [1] A (current byte of sprite) >> 1 : ABAB ABAB -> xABA BABA - and c ;; [2] A |= Mask (0x55) : xAxA xAxA - - cp d ;; [1] Test if pixel (A) is the old colour to be replaced (D) - jr nz, readPixelB ;; [2/3] If not equal go to next pixel + ld h, a ;; [1] H = A (current colorized sprite) : xBxB xBxB + ld a, l ;; [1] L = A current Byte of sprite : ABAB ABAB + rrca ;; [1] A (current byte of sprite) >> 1 : ABAB ABAB -> xABA BABA + and c ;; [2] A |= Mask (0x55) : xAxA xAxA + + cp d ;; [1] Test if pixel (A) is the old colour to be replaced (D) + jr nz, readPixelB ;; [2/3] If not equal go to next pixel ld a, e ;; [1] else A = new colour to set (E) - + readPixelB: - rlca ;; [1] A = xAxA xAxA << 1 : AxAx AxAx - or h ;; [1] A |= H (xBxB xBxB) : ABAB ABAB + rlca ;; [1] A = xAxA xAxA << 1 : AxAx AxAx + or h ;; [1] A |= H (xBxB xBxB) : ABAB ABAB drawByte: ld h, b ;; [1] H = B (Masked table adress High Byte) - ld l, a ;; [1] Access mask table element (table must be 256-byte aligned) - exx ;; [1] Switch to Alternate registers - - ld a, (de) ;; [2] Get the value of the byte of the screen where we are going to draw - exx ;; [1] Switch to Default registers - - and (hl) ;; [2] Erase background part that is to be overwritten (Mask step 1) - or l ;; [1] Add up background and sprite information in one byte (Mask step 2) - exx ;; [1] Switch to Alternate registers - - ld (de), a ;; [2] Save modified background + sprite data information into memory + ld l, a ;; [1] Access mask table element (table must be 256-byte aligned) + exx ;; [1] Switch to Alternate registers + + ld a, (de) ;; [2] Get the value of the byte of the screen where we are going to draw + exx ;; [1] Switch to Default registers + + and (hl) ;; [2] Erase background part that is to be overwritten (Mask step 1) + or l ;; [1] Add up background and sprite information in one byte (Mask step 2) + exx ;; [1] Switch to Alternate registers + + ld (de), a ;; [2] Save modified background + sprite data information into memory - inc hl ;; [2] Next byte sprite source - inc de ;; [2] Next byte sprite colorized - djnz lineLoop ;; [3] Decrement B (Width) if B != 0 goto lineLoop - - dec c ;; [1] Decrement C (Height) - jr z, end ;; [2/3] If C == O goto end + inc hl ;; [2] Next byte sprite source + inc de ;; [2] Next byte sprite colorized + djnz lineLoop ;; [3] Decrement B (Width) if B != 0 goto lineLoop + + dec c ;; [1] Decrement C (Height) + jr z, end ;; [2/3] If C == O goto end - pop de ;; [3] Restore DE start line (DestMem) + pop de ;; [3] Restore DE start line (DestMem) ld a, d ;; [1] Start of next pixel line normally is 0x0800 bytes away. add #0x08 ;; [2] so we add it to DE (just by adding 0x08 to D) ld d, a ;; [1] - and #0x38 ;; [2] We check if we have crossed memory boundary (every 8 pixel lines).. - + and #0x38 ;; [2] We check if we have crossed memory boundary (every 8 pixel lines).. + jr nz, convertLoop ;; [2/3] .. by checking the 4 bits that identify present memory line. ;; .... If 0, we have crossed boundaries @@ -184,11 +205,11 @@ dms_sprite_8bit_boundary_crossed: ld a, d ;; [1] -- which effectively is the same as moving it 1 bank backwards and then adc #0xC0 ;; [2] -- 50 bytes forwards (which is what we want to move it to the next pixel line) ld d, a ;; [1] -- Calculations are made with 8 bit maths as it is faster than other alternatives here - - jr convertLoop ;; [3] Jump to continue with next pixel line + + jr convertLoop ;; [3] Jump to continue with next pixel line end: pop de ;; [3] Empty stack by getting last element (DestMem) - ;; Return is included in bindings - - + ;; Return is included in bindings + + diff --git a/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteMaskedAlignedColorizeM0_asmbindings.s b/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteMaskedAlignedColorizeM0_asmbindings.s index 868def72a..f566e8fc5 100644 --- a/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteMaskedAlignedColorizeM0_asmbindings.s +++ b/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteMaskedAlignedColorizeM0_asmbindings.s @@ -1,7 +1,7 @@ ;;-----------------------------LICENSE NOTICE------------------------------------ ;; This file is part of CPCtelera: An Amstrad CPC Game Engine -;; Copyright (C) 2018 Arnaud Bouche (@Arnaud6128) -;; Copyright (C) 2018 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) +;; Copyright (C) 2017 Arnaud Bouche (@Arnaud6128) +;; Copyright (C) 2017 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) ;; ;; This program is free software: you can redistribute it and/or modify ;; it under the terms of the GNU Lesser General Public License as published by @@ -18,7 +18,7 @@ ;;------------------------------------------------------------------------------- .module cpct_sprites -.include "../macros/cpct_undocumentedOpcodes.s" +.include "../../../macros/cpct_undocumentedOpcodes.h.s" ;; ;; ASM bindings for <cpct_drawSpriteMaskedAlignedColorizeM0> @@ -27,6 +27,7 @@ cpct_drawSpriteMaskedAlignedColorizeM0_asm:: ;; Assembly entry point ;; GET Parameters from the stack ld (dms_restore_ix + 2), ix ;; [6] Save IX to restore it before returning + pop hl ;; [3] HL = Return Address .include /cpct_drawSpriteMaskedAlignedColorizeM0.asm/ diff --git a/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteMaskedAlignedColorizeM0_cbindings.s b/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteMaskedAlignedColorizeM0_cbindings.s index 01d9eee57..f8953c60b 100644 --- a/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteMaskedAlignedColorizeM0_cbindings.s +++ b/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteMaskedAlignedColorizeM0_cbindings.s @@ -1,7 +1,7 @@ ;;-----------------------------LICENSE NOTICE------------------------------------ ;; This file is part of CPCtelera: An Amstrad CPC Game Engine -;; Copyright (C) 2018 Arnaud Bouche (@Arnaud6128) -;; Copyright (C) 2018 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) +;; Copyright (C) 2017 Arnaud Bouche (Arnaud6128) +;; Copyright (C) 2017 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) ;; ;; This program is free software: you can redistribute it and/or modify ;; it under the terms of the GNU Lesser General Public License as published by @@ -18,12 +18,12 @@ ;;------------------------------------------------------------------------------- .module cpct_sprites -.include "../macros/cpct_undocumentedOpcodes.s" +.include "../../../macros/cpct_undocumentedOpcodes.h.s" ;; ;; C bindings for <cpct_drawSpriteMaskedAlignedColorizeM0> ;; -;; 39 us, 8 bytes +;; 39 us, 16 bytes ;; _cpct_drawSpriteMaskedAlignedColorizeM0:: @@ -37,10 +37,13 @@ _cpct_drawSpriteMaskedAlignedColorizeM0:: pop bc ;; [5] BC' = (B = Sprite Height, C = Width) exx ;; [1] Switch to Default registers - pop de ;; [3] DE = Table Mask address + pop de ;; [3] DE = (D = newColor, E = oldColor) - push hl ;; [4] Put returning address in the stack again - ;; as this function uses __z88dk_callee convention + ex (sp), hl ;; [6] HL = Table Mask address + ;; ... and leave Return Address at (SP) as we don't need to restore + ;; ... stack status because callin convention is __z88dk_callee + + ex de, hl ;; [1] HL <-> DE .include /cpct_drawSpriteMaskedAlignedColorizeM0.asm/ diff --git a/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteMaskedColorizeM0.asm b/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteMaskedColorizeM0.asm index 7862cdaeb..8f63f4c99 100644 --- a/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteMaskedColorizeM0.asm +++ b/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteMaskedColorizeM0.asm @@ -1,7 +1,7 @@ ;;-----------------------------LICENSE NOTICE------------------------------------ ;; This file is part of CPCtelera: An Amstrad CPC Game Engine -;; Copyright (C) 2018 Arnaud Bouche (@Arnaud6128) -;; Copyright (C) 2018 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) +;; Copyright (C) 2017 Arnaud Bouche +;; Copyright (C) 2017 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) ;; ;; This program is free software: you can redistribute it and/or modify ;; it under the terms of the GNU Lesser General Public License as published by @@ -18,6 +18,8 @@ ;;------------------------------------------------------------------------------- .module cpct_sprites +.globl dc_mode0_ct + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; Function: cpct_drawSpriteMaskedColorizeM0 @@ -25,13 +27,15 @@ ;; Directly replace a color and draw a sprite Masked to video memory. ;; ;; C Definition: -;; void <cpct_drawSpriteMaskedColorizeM0> (void* *sprite*, void* *memory*, <u8> *width*, <u8> *height*) __z88dk_callee; +;; void <cpct_drawSpriteMaskedColorizeM0> (void* *sprite*, void* *memory*, <u8> *width*, <u8> *height*, <u8> *oldColor*, <u8> *newColor*) __z88dk_callee; ;; -;; Input Parameters (6 bytes): +;; Input Parameters (8 bytes): ;; (2B HL') sprite - Source Sprite Pointer (array of pixel data) ;; (2B DE') memory - Destination video memory pointer ;; (1B C' ) height - Sprite Height in bytes (>0) ;; (1B B' ) width - Sprite Width in *bytes* (Beware, *not* in pixels!) +;; (1B L ) oldColor - Color to replace +;; (1B H ) newColor - New color ;; ;; Assembly call (Input parameters on registers): ;; > call cpct_drawSpriteMaskedColorizeM0_asm @@ -57,6 +61,8 @@ ;; There is no practical upper limit to this value. Height of a sprite in ;; bytes and pixels is the same value, as bytes only group consecutive pixels in ;; the horizontal space. +;; * *oldColor* must be the index of color (0 to 15) to replace +;; * *newColor* must be the index of the new color (0 to 15) ;; ;; Known limitations: ;; * This function does not do any kind of boundary check or clipping. If you @@ -74,21 +80,20 @@ ;; * This function requires the CPC firmware to be DISABLED. Otherwise, random crashes might happen due to side effects. ;; ;; Destroyed Register values: -;; AF, BC, DE, BC', DE', HL', IX +;; AF, BC, DE, HL, BC', DE', HL', IX ;; ;; Required memory: -;; C-bindings - 165 bytes -;; ASM-bindings - 160 bytes +;; C-bindings - 115 bytes +;; ASM-bindings - 102 bytes ;; ;; Time Measures: ;; (start code) ;; Case | microSecs (us) | CPU Cycles ;; ---------------------------------------------------------------- -;; Best | | -;; Worst | | +;; Best | 29 + (50 + 36W)H | 116 + (200 + 144W)H ;; ---------------------------------------------------------------- -;; W=2,H=16 | | -;; W=4,H=32 | | +;; W=2,H=16 | 1981 | 7924 +;; W=4,H=32 | 6237 | 24948 ;; ---------------------------------------------------------------- ;; Asm saving | -16 | -64 ;; ---------------------------------------------------------------- @@ -102,21 +107,34 @@ ;; Thanks to all of them for their help and support. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -.globl _cpct_color_old -.globl _cpct_color_new +;; Macro to convert Pixel to xAxC xBxD format +.macro convertPixel + ;; From cpct_px2byteM0 + ld bc, #dc_mode0_ct ;; [3] BC points to conversion table (dc_mode0_ct) + + ;; Compute BC += A + add c ;; [1] | C += A + ld c, a ;; [1] | + sub a ;; [1] A = 0 (preserving Carry Flag) + adc b ;; [1] | B += Carry + ld b, a ;; [1] | + + ;; A = *(BC + A) + ld a, (bc) ;; [2] A = Value stored at the table pointed by BC +.endm - ;; newColor to pixel format (E) - ld a, (_cpct_color_new);; [4] A = mem new color index + ;; Convert newColor to pixel format (E) + ld a, h ;; [1] A = H new color index + convertPixel ;; [10] | Convert into A ld e, a ;; [1] | E = A new color : xAxC xBxD - ;; oldColor to pixel format (D) - ld a, (_cpct_color_old);; [4] A = mem old color index + ;; Convert oldColor to pixel format (D) + ld a, l ;; [1] A = L old color index + convertPixel ;; [10] | Convert into A ld d, a ;; [1] | D = A old color : xAxC xBxD ld c, #0x55 ;; [2] C = Mask to get pixel A : xAxC xBxD - ld c, #0x55 ;; [2] C = Mask to get pixel A : xAxC xBxD - exx ;; [1] Switch to Alternate registers ld__ixl_c ;; [1] IXL = C (Width) diff --git a/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteMaskedColorizeM0_asmbindings.s b/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteMaskedColorizeM0_asmbindings.s index a8806e008..48bc1ef3c 100644 --- a/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteMaskedColorizeM0_asmbindings.s +++ b/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteMaskedColorizeM0_asmbindings.s @@ -18,7 +18,7 @@ ;;------------------------------------------------------------------------------- .module cpct_sprites -.include "../macros/cpct_undocumentedOpcodes.s" +.include "../../../macros/cpct_undocumentedOpcodes.h.s" ;; ;; ASM bindings for <cpct_drawSpriteMaskedColorizeM0> @@ -27,6 +27,7 @@ cpct_drawSpriteMaskedColorizeM0_asm:: ;; Assembly entry point ;; GET Parameters from the stack ld (dms_restore_ix + 2), ix ;; [6] Save IX to restore it before returning + pop hl ;; [3] HL = Return Address .include /cpct_drawSpriteMaskedColorizeM0.asm/ diff --git a/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteMaskedColorizeM0_cbindings.s b/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteMaskedColorizeM0_cbindings.s index 1f0fd6e66..18f336eb5 100644 --- a/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteMaskedColorizeM0_cbindings.s +++ b/cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteMaskedColorizeM0_cbindings.s @@ -18,18 +18,18 @@ ;;------------------------------------------------------------------------------- .module cpct_sprites -.include "../macros/cpct_undocumentedOpcodes.s" +.include "../../../macros/cpct_undocumentedOpcodes.h.s" ;; ;; C bindings for <cpct_drawSpriteMaskedColorizeM0> ;; -;; 33 us, 8 bytes +;; 33 us, 13 bytes ;; _cpct_drawSpriteMaskedColorizeM0:: ;; GET Parameters from the stack ld (dms_restore_ix + 2), ix ;; [6] Save IX to restore it before returning - pop de ;; [3] DE = Return Address + pop hl ;; [3] HL = Return Address exx pop hl ;; [3] HL' = Source address (Sprite) @@ -37,8 +37,9 @@ _cpct_drawSpriteMaskedColorizeM0:: pop bc ;; [5] BC' = (B = Sprite Height, C = Width) exx - push de ;; [4] Put returning address in the stack again - ;; as this function uses __z88dk_callee convention + ex (sp), hl ;; [6] HL = (H = newColor, L = oldColor) + ;; ... and leave Return Address at (SP) as we don't need to restore + ;; ... stack status because callin convention is __z88dk_callee .include /cpct_drawSpriteMaskedColorizeM0.asm/ diff --git a/cpctelera/src/sprites/colorReplace/M0/cpct_replaceColor.s b/cpctelera/src/sprites/colorReplace/M0/cpct_replaceColor.s deleted file mode 100644 index 260c2ea15..000000000 --- a/cpctelera/src/sprites/colorReplace/M0/cpct_replaceColor.s +++ /dev/null @@ -1,44 +0,0 @@ -;;-----------------------------LICENSE NOTICE------------------------------------ -;; This file is part of CPCtelera: An Amstrad CPC Game Engine -;; Copyright (C) 2018 Arnaud Bouche (@Arnaud6128) -;; Copyright (C) 2018 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) -;; -;; This program is free software: you can redistribute it and/or modify -;; it under the terms of the GNU Lesser General Public License as published by -;; the Free Software Foundation, either version 3 of the License, or -;; (at your option) any later version. -;; -;; This program is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU Lesser General Public License for more details. -;; -;; You should have received a copy of the GNU Lesser General Public License -;; along with this program. If not, see <http://www.gnu.org/licenses/>. -;;------------------------------------------------------------------------------- -.module cpct_sprites - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; -;; Variables: cpct_color_old, cpct_color_new -;; -;; Contains the colors to be used by theses functions: -;; * cpct_setReplaceColors -;; * cpct_spriteColorizeM0 -;; * cpct_spriteColorizeM1 -;; * cpct_drawSpriteColorizeM0 -;; * cpct_drawSpriteColorizeM1 -;; -;; C Definition: -;; <u8> <cpct_color_old>; -;; <u8> <cpct_color_new>; -;; -;; Known limitations: -;; * These color are used for Mode0 (0 to 15) and Mode1 (0 to 3) -;; * You may assing a value to this seed direcly from C or ASM. If directly accessed -;; from ASM, do not forget to put an underscore in front (_cpct_color_old and _cpct_color_new). -;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -_cpct_color_old:: .db #00 -_cpct_color_new:: .db #00 \ No newline at end of file diff --git a/cpctelera/src/sprites/colorReplace/M0/cpct_setReplaceColorsM0.asm b/cpctelera/src/sprites/colorReplace/M0/cpct_setReplaceColorsM0.asm deleted file mode 100644 index 47c9308a7..000000000 --- a/cpctelera/src/sprites/colorReplace/M0/cpct_setReplaceColorsM0.asm +++ /dev/null @@ -1,87 +0,0 @@ -;;-----------------------------LICENSE NOTICE------------------------------------ -;; This file is part of CPCtelera: An Amstrad CPC Game Engine -;; Copyright (C) 2018 Arnaud Bouche (@Arnaud6128) -;; Copyright (C) 2018 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) -;; -;; This program is free software: you can redistribute it and/or modify -;; it under the terms of the GNU Lesser General Public License as published by -;; the Free Software Foundation, either version 3 of the License, or -;; (at your option) any later version. -;; -;; This program is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU Lesser General Public License for more details. -;; -;; You should have received a copy of the GNU Lesser General Public License -;; along with this program. If not, see <http://www.gnu.org/licenses/>. -;;------------------------------------------------------------------------------- -.module cpct_sprites - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; -;; Function: cpct_setReplaceColorsM0 -;; -;; Sets the colors to be used with the replace colors for Mode 0 functions -;; -;; C Definition: -;; void <cpct_setReplaceColorsM0> (<u8> *oldColor*, <u8> *newColor*) __z88dk_fastcall; -;; -;; Input Parameters (2 bytes): -;; (1B D) *oldColor* - Color to be replaced. -;; (1B E) *newColor* - Color to set. -;; -;; Assembly call: -;; > call cpct_setReplaceColorsM0 -;; -;; Parameter Restrictions: -;; * There is not check on the color value according to the Mode 0 (0 to 15) -;; -;; Destroyed Register values: -;; A, BC, DE -;; -;; Required memory: -;; 8 bytes -;; -;; Time Measures: -;; (start code) -;; Case | microSecs (us) | CPU Cycles -;; ----------------------------------------- -;; Any | 14 | 56 -;; ----------------------------------------- -;; (end code) -;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -.globl dc_mode0_ct - -;; Macro to convert Pixel to xAxC xBxD format -.macro convertPixel - ;; From cpct_px2byteM0 - ld bc, #dc_mode0_ct ;; [3] BC points to conversion table (dc_mode0_ct) - - ;; Compute BC += A - add c ;; [1] | C += A - ld c, a ;; [1] | - sub a ;; [1] A = 0 (preserving Carry Flag) - adc b ;; [1] | B += Carry - ld b, a ;; [1] | - - ;; A = *(BC + A) - ld a, (bc) ;; [2] A = Value stored at the table pointed by BC -.endm - -.globl _cpct_color_old -.globl _cpct_color_new - - ;; Convert New color - ld a, h ;; [1] A = H new color - convertPixel ;; [10] | Convert into A - ld (_cpct_color_new), a ;; [3] | store color in memory - - ;; Convert Old color - ld a, l ;; [1] A = L old color - convertPixel ;; [10] | Convert into A - ld (_cpct_color_old), a ;; [3] | store color in memory - - ret ;; [3] \ No newline at end of file diff --git a/cpctelera/src/sprites/colorReplace/M0/cpct_setReplaceColorsM0_cbinding.s b/cpctelera/src/sprites/colorReplace/M0/cpct_setReplaceColorsM0_cbinding.s deleted file mode 100644 index 5792fed64..000000000 --- a/cpctelera/src/sprites/colorReplace/M0/cpct_setReplaceColorsM0_cbinding.s +++ /dev/null @@ -1,31 +0,0 @@ -;;-----------------------------LICENSE NOTICE------------------------------------ -;; This file is part of CPCtelera: An Amstrad CPC Game Engine -;; Copyright (C) 2018 Arnaud Bouche (@Arnaud6128) -;; Copyright (C) 2018 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) -;; -;; This program is free software: you can redistribute it and/or modify -;; it under the terms of the GNU Lesser General Public License as published by -;; the Free Software Foundation, either version 3 of the License, or -;; (at your option) any later version. -;; -;; This program is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU Lesser General Public License for more details. -;; -;; You should have received a copy of the GNU Lesser General Public License -;; along with this program. If not, see <http://www.gnu.org/licenses/>. -;;------------------------------------------------------------------------------- -.module cpct_sprites - -;; -;; C bindings for <cpct_px2byteM0> -;; -;; 9 us, 2 bytes -;; -_cpct_setReplaceColorsM0:: - ;; Recover parameters from the stack - pop hl ;; [3] HL = Return Address - ex (sp), hl ;; [6] HL => L : Old Color, H : New Color - -.include /cpct_setReplaceColorsM0.asm/ \ No newline at end of file diff --git a/cpctelera/src/sprites/colorReplace/M0/cpct_spriteColorizeM0.asm b/cpctelera/src/sprites/colorReplace/M0/cpct_spriteColorizeM0.asm index a6d9090c0..f319db09c 100644 --- a/cpctelera/src/sprites/colorReplace/M0/cpct_spriteColorizeM0.asm +++ b/cpctelera/src/sprites/colorReplace/M0/cpct_spriteColorizeM0.asm @@ -25,13 +25,15 @@ ;; Replace a color in a sprite and copy to another or the same sprite. ;; ;; C Definition: -;; void <cpct_spriteColorizeM0> (void* *sprite*, void* *spriteColor*, <u8> *width*, <u8> *height*) __z88dk_callee; +;; void <cpct_spriteColorizeM0> (void* *sprite*, void* *spriteColor*, <u8> *width*, <u8> *height*, <u8> *oldColor*, <u8> *newColor*) __z88dk_callee; ;; ;; Input Parameters (6 bytes): ;; (2B HL') sprite - Source Sprite Pointer (array of pixel data) ;; (2B DE') spriteColor - Destination Sprite Pointer (can be also the Source Sprite) (array of pixel data) ;; (1B C' ) height - Sprite Height in bytes (>0) ;; (1B B' ) width - Sprite Width in *bytes* (Beware, *not* in pixels!) +;; (1B L ) oldColor - Color to replace +;; (1B H ) newColor - New color ;; ;; Assembly call (Input parameters on registers): ;; > call cpct_spriteColorizeM0_asm @@ -49,31 +51,33 @@ ;; There is no practical upper limit to this value. Height of a sprite in ;; bytes and pixels is the same value, as bytes only group consecutive pixels in ;; the horizontal space. +;; * *oldColor* must be the index of color (0 to 15) to replace +;; * *newColor* must be the index of the new color (0 to 15) ;; ;; Known limitations: ;; * This function *will not work from ROM*, as it uses self-modifying code. ;; * This function requires the CPC firmware to be DISABLED. Otherwise, random crashes might happen due to side effects. ;; ;; Destroyed Register values: -;; AF, BC, DE, BC', DE', HL', IX +;; AF, BC, DE, HL, BC', DE', HL', IX ;; ;; Required memory: -;; C-bindings - 165 bytes -;; ASM-bindings - 160 bytes +;; C-bindings - 81 bytes +;; ASM-bindings - 67 bytes ;; ;; Time Measures: ;; (start code) ;; Case | microSecs (us) | CPU Cycles ;; ---------------------------------------------------------------- -;; | 29 + (33 + 4W)H | 116 + (132 + 16W)H +;; | 29 + (6 + 33W)H | 116 + (24 + 132W)H ;; ---------------------------------------------------------------- -;; W=2,H=16 | 685 | 2740 -;; W=4,H=32 | 1597 | 6388 +;; W=2,H=16 | 1181 | 4724 +;; W=4,H=32 | 4445 | 17780 ;; ---------------------------------------------------------------- ;; Asm saving | -16 | -64 ;; ---------------------------------------------------------------- ;; (end code) -;; W = *width* in bytes, H = *height* in bytes, HH = [(H-1)/8] +;; W = *width* in bytes, H = *height* in bytes ;; ;; Credits: ;; Original routine optimized by @Docent and discussed in CPCWiki : @@ -82,19 +86,35 @@ ;; Thanks to all of them for their help and support. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -.globl _cpct_color_old -.globl _cpct_color_new +.globl dc_mode0_ct - ;; newColor to pixel format (E) - ld a, (_cpct_color_new);; [4] A = mem new color index +;; Macro to convert Pixel to xAxC xBxD format +.macro convertPixel + ;; From cpct_px2byteM0 + ld bc, #dc_mode0_ct ;; [3] BC points to conversion table (dc_mode0_ct) + + ;; Compute BC += A + add c ;; [1] | C += A + ld c, a ;; [1] | + sub a ;; [1] A = 0 (preserving Carry Flag) + adc b ;; [1] | B += Carry + ld b, a ;; [1] | + + ;; A = *(BC + A) + ld a, (bc) ;; [2] A = Value stored at the table pointed by BC +.endm + + ;; Convert newColor to pixel format (E) + ld a, h ;; [1] A = H new color index + convertPixel ;; [10] | Convert into A ld e, a ;; [1] | E = A new color : xAxC xBxD - ;; oldColor to pixel format (D) - ld a, (_cpct_color_old);; [4] A = mem old color index + ;; Convert oldColor to pixel format (D) + ld a, l ;; [1] A = L old color index + convertPixel ;; [10] | Convert into A ld d, a ;; [1] | D = A old color : xAxC xBxD ld c, #0x55 ;; [2] C = Mask to get pixel A : xAxC xBxD - exx ;; [1] Switch to Alternate registers ld__ixl_c ;; [1] IXL = C (Width) @@ -104,7 +124,7 @@ convertLoop: ld__b_ixl ;; [2] B = IXL (Sprite Width) lineLoop: - ld a, (hl) ;; [2] A = (HL') current Byte of sprite + ld a, (hl) ;; [2] A = (HL) current Byte of sprite exx ;; [1] Switch to Default registers ld l, a ;; [1] L = A current Byte of sprite : ABAB ABAB @@ -139,7 +159,8 @@ setByte: nextLine: dec c ;; [1] Decrement C (Height) - jr nz, convertLoop ;; [1] If != O goto convertLoop + jr nz, convertLoop ;; [2/3] If != O goto convertLoop end: - ;; Return is included in bindings \ No newline at end of file + ;; Return is included in bindings + diff --git a/cpctelera/src/sprites/colorReplace/M0/cpct_spriteColorizeM0_asmbindings.s b/cpctelera/src/sprites/colorReplace/M0/cpct_spriteColorizeM0_asmbindings.s index 1362dbb6b..3339b8ea5 100644 --- a/cpctelera/src/sprites/colorReplace/M0/cpct_spriteColorizeM0_asmbindings.s +++ b/cpctelera/src/sprites/colorReplace/M0/cpct_spriteColorizeM0_asmbindings.s @@ -18,19 +18,19 @@ ;;------------------------------------------------------------------------------- .module cpct_sprites -.include "../macros/cpct_undocumentedOpcodes.s" +.include "../../../macros/cpct_undocumentedOpcodes.h.s" ;; ;; ASM bindings for <cpct_spriteColorizeM0> ;; cpct_spriteColorizeM0_asm:: ;; Assembly entry point - ;; GET Parameters from the stack - ld (dms_restore_ix + 2), ix ;; [6] Save IX to restore it before returning + ;; GET Parameters from the stack + ld (dms_restore_ix + 2), ix ;; [6] Save IX to restore it before returning + pop hl ;; [3] HL = Return Address .include /cpct_spriteColorizeM0.asm/ dms_restore_ix: ld ix, #0000 ;; [4] Restore IX before returning - ret ;; [3] Return to caller - + ret ;; [3] Return to caller \ No newline at end of file diff --git a/cpctelera/src/sprites/colorReplace/M0/cpct_spriteColorizeM0_cbindings.s b/cpctelera/src/sprites/colorReplace/M0/cpct_spriteColorizeM0_cbindings.s index 4d67122d8..27d164918 100644 --- a/cpctelera/src/sprites/colorReplace/M0/cpct_spriteColorizeM0_cbindings.s +++ b/cpctelera/src/sprites/colorReplace/M0/cpct_spriteColorizeM0_cbindings.s @@ -18,7 +18,7 @@ ;;------------------------------------------------------------------------------- .module cpct_sprites -.include "../macros/cpct_undocumentedOpcodes.s" +.include "../../../macros/cpct_undocumentedOpcodes.h.s" ;; ;; C bindings for <cpct_spriteColorizeM0> @@ -29,19 +29,20 @@ _cpct_spriteColorizeM0:: ;; GET Parameters from the stack ld (dms_restore_ix + 2), ix ;; [6] Save IX to restore it before returning - pop de ;; [3] DE = Return Address + pop hl ;; [3] HL = Return Address - exx ;; [1] Swap to alternate registers + exx pop hl ;; [3] HL' = Source address (Sprite) pop de ;; [3] DE' = Destination Sprite color pop bc ;; [5] BC' = (B = Sprite Height, C = Width) - exx ;; [1] Swap to default registers + exx - push de ;; [4] Put returning address in the stack again - ;; as this function uses __z88dk_callee convention + ex (sp), hl ;; [6] HL = (H = newColor, L = oldColor) + ;; ... and leave Return Address at (SP) as we don't need to restore + ;; ... stack status because callin convention is __z88dk_callee .include /cpct_spriteColorizeM0.asm/ dms_restore_ix: ld ix, #0000 ;; [4] Restore IX before returning - ret ;; [3] Return to caller + ret ;; [3] Return to caller \ No newline at end of file diff --git a/cpctelera/src/sprites/colorReplace/M0/cpct_spriteMaskedColorizeM0.asm b/cpctelera/src/sprites/colorReplace/M0/cpct_spriteMaskedColorizeM0.asm index 6ebf9798b..37a32f02e 100644 --- a/cpctelera/src/sprites/colorReplace/M0/cpct_spriteMaskedColorizeM0.asm +++ b/cpctelera/src/sprites/colorReplace/M0/cpct_spriteMaskedColorizeM0.asm @@ -1,6 +1,6 @@ ;;-----------------------------LICENSE NOTICE------------------------------------ ;; This file is part of CPCtelera: An Amstrad CPC Game Engine -;; Copyright (C) 2018 Arnaud Bouche (@Arnaud6128)) +;; Copyright (C) 2018 Arnaud Bouche (@Arnaud6128) ;; Copyright (C) 2018 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) ;; ;; This program is free software: you can redistribute it and/or modify @@ -25,13 +25,15 @@ ;; Replace a color in a Masked sprite and copy to another or the same sprite. ;; ;; C Definition: -;; void <cpct_spriteMaskedColorizeM0> (void* *sprite*, void* *spriteColor*, <u8> *width*, <u8> *height*) __z88dk_callee; +;; void <cpct_spriteMaskedColorizeM0> (void* *sprite*, void* *spriteColor*, <u8> *width*, <u8> *height*, <u8> *oldColor*, <u8> *newColor*) __z88dk_callee; ;; ;; Input Parameters (6 bytes): ;; (2B HL') sprite - Source Sprite Pointer (array of pixel data) ;; (2B DE') spriteColor - Destination Sprite Pointer (can be also the Source Sprite) (array of pixel data) ;; (1B C') height - Sprite Height in bytes (>0) ;; (1B B') width - Sprite Width in *bytes* (Beware, *not* in pixels!) +;; (1B L) oldColor - Color to replace +;; (1B H) newColor - New color ;; ;; Assembly call (Input parameters on registers): ;; > call cpct_spriteMaskedColorizeM0_asm @@ -55,17 +57,19 @@ ;; There is no practical upper limit to this value. Height of a sprite in ;; bytes and pixels is the same value, as bytes only group consecutive pixels in ;; the horizontal space. +;; * *oldColor* must be the index of color (0 to 15) to replace +;; * *newColor* must be the index of the new color (0 to 15) ;; ;; Known limitations: ;; * This function *will not work from ROM*, as it uses self-modifying code. ;; * This function requires the CPC firmware to be DISABLED. Otherwise, random crashes might happen due to side effects. ;; ;; Destroyed Register values: -;; AF, BC, DE, BC', DE', HL', IX +;; AF, BC, DE, HL, BC', DE', HL', IX ;; ;; Required memory: -;; C-bindings - 165 bytes -;; ASM-bindings - 160 bytes +;; C-bindings - 87 bytes +;; ASM-bindings - 73 bytes ;; ;; Time Measures: ;; (start code) @@ -88,19 +92,35 @@ ;; Thanks to all of them for their help and support. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -.globl _cpct_color_old -.globl _cpct_color_new +.globl dc_mode0_ct - ;; newColor to pixel format (E) - ld a, (_cpct_color_new);; [4] A = mem new color index +;; Macro to convert Pixel to xAxC xBxD format +.macro convertPixel + ;; From cpct_px2byteM0 + ld bc, #dc_mode0_ct ;; [3] BC points to conversion table (dc_mode0_ct) + + ;; Compute BC += A + add c ;; [1] | C += A + ld c, a ;; [1] | + sub a ;; [1] A = 0 (preserving Carry Flag) + adc b ;; [1] | B += Carry + ld b, a ;; [1] | + + ;; A = *(BC + A) + ld a, (bc) ;; [2] A = Value stored at the table pointed by BC +.endm + + ;; Convert newColor to pixel format (E) + ld a, h ;; [1] A = H new color index + convertPixel ;; [10] | Convert into A ld e, a ;; [1] | E = A new color : xAxC xBxD - ;; oldColor to pixel format (D) - ld a, (_cpct_color_old);; [4] A = mem old color index + ;; Convert oldColor to pixel format (D) + ld a, l ;; [1] A = L old color index + convertPixel ;; [10] | Convert into A ld d, a ;; [1] | D = A old color : xAxC xBxD ld c, #0x55 ;; [2] C = Mask to get pixel A : xAxC xBxD - exx ;; [1] Switch to Alternate registers ld__ixl_c ;; [1] IXL = C (Width) @@ -148,8 +168,8 @@ setByte: inc de ;; [2] Next byte sprite colorized djnz lineLoop ;; [3] Decrement B (Width) if != 0 goto lineLoop - dec c ;; [1] Decrement C (Height) - jr nz, convertLoop ;; [2/3] If C == O goto end + dec c ;; [1] Decrement C (Height) + jr nz, convertLoop ;; [2/3] If C == O goto end end: ;; Return is included in bindings \ No newline at end of file diff --git a/cpctelera/src/sprites/colorReplace/M0/cpct_spriteMaskedColorizeM0_asmbindings.s b/cpctelera/src/sprites/colorReplace/M0/cpct_spriteMaskedColorizeM0_asmbindings.s index af949e8a6..04b8fcf88 100644 --- a/cpctelera/src/sprites/colorReplace/M0/cpct_spriteMaskedColorizeM0_asmbindings.s +++ b/cpctelera/src/sprites/colorReplace/M0/cpct_spriteMaskedColorizeM0_asmbindings.s @@ -1,6 +1,6 @@ ;;-----------------------------LICENSE NOTICE------------------------------------ ;; This file is part of CPCtelera: An Amstrad CPC Game Engine -;; Copyright (C) 2018 Arnaud Bouche (Arnaud6128) +;; Copyright (C) 2018 Arnaud Bouche (@Arnaud6128) ;; Copyright (C) 2018 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) ;; ;; This program is free software: you can redistribute it and/or modify @@ -18,7 +18,7 @@ ;;------------------------------------------------------------------------------- .module cpct_sprites -.include "../macros/cpct_undocumentedOpcodes.s" +.include "../../../macros/cpct_undocumentedOpcodes.h.s" ;; ;; ASM bindings for <cpct_spriteMaskedColorizeM0> @@ -27,6 +27,7 @@ cpct_spriteMaskedColorizeM0_asm:: ;; Assembly entry point ;; GET Parameters from the stack ld (dms_restore_ix + 2), ix ;; [6] Save IX to restore it before returning + pop hl ;; [3] HL = Return Address .include /cpct_spriteMaskedColorizeM0.asm/ diff --git a/cpctelera/src/sprites/colorReplace/M0/cpct_spriteMaskedColorizeM0_cbindings.s b/cpctelera/src/sprites/colorReplace/M0/cpct_spriteMaskedColorizeM0_cbindings.s index c74a0ea07..3dad1ae84 100644 --- a/cpctelera/src/sprites/colorReplace/M0/cpct_spriteMaskedColorizeM0_cbindings.s +++ b/cpctelera/src/sprites/colorReplace/M0/cpct_spriteMaskedColorizeM0_cbindings.s @@ -18,7 +18,7 @@ ;;------------------------------------------------------------------------------- .module cpct_sprites -.include "../macros/cpct_undocumentedOpcodes.s" +.include "../../../macros/cpct_undocumentedOpcodes.h.s" ;; ;; C bindings for <cpct_spriteMaskedColorizeM0> @@ -29,7 +29,7 @@ _cpct_spriteMaskedColorizeM0:: ;; GET Parameters from the stack ld (dms_restore_ix + 2), ix ;; [6] Save IX to restore it before returning - pop de ;; [3] DE = Return Address + pop hl ;; [3] HL = Return Address exx pop hl ;; [3] HL' = Source address (Sprite) @@ -37,8 +37,9 @@ _cpct_spriteMaskedColorizeM0:: pop bc ;; [5] BC' = (B = Sprite Height, C = Width) exx - push de ;; [4] Put returning address in the stack again - ;; as this function uses __z88dk_callee convention + ex (sp), hl ;; [6] HL = (H = newColor, L = oldColor) + ;; ... and leave Return Address at (SP) as we don't need to restore + ;; ... stack status because callin convention is __z88dk_callee .include /cpct_spriteMaskedColorizeM0.asm/ diff --git a/cpctelera/src/sprites/colorReplace/colorReplace.h b/cpctelera/src/sprites/colorReplace/colorReplace.h index 79cc0f19a..d5675f624 100644 --- a/cpctelera/src/sprites/colorReplace/colorReplace.h +++ b/cpctelera/src/sprites/colorReplace/colorReplace.h @@ -28,20 +28,17 @@ #ifndef CPCT_COLORREPLACE_H #define CPCT_COLORREPLACE_H -// Function to set colors to replace M0 -extern void cpct_setReplaceColorsM0(u8 oldColor, u8 newColor) __z88dk_callee; - // Functions to replace a color in sprite M0 -extern void cpct_spriteColorizeM0(u8* sprite, u8* spriteColor, u8 width, u8 height) __z88dk_callee; -extern void cpct_spriteMaskedColorizeM0(u8* sprite, u8* spriteColor, u8 width, u8 height) __z88dk_callee; +extern void cpct_spriteColorizeM0(u8* sprite, u8* spriteColor, u8 width, u8 height, u8 oldColor, u8 newColor) __z88dk_callee; +extern void cpct_spriteMaskedColorizeM0(u8* sprite, u8* spriteColor, u8 width, u8 height, u8 oldColor, u8 newColor) __z88dk_callee; // Functions to draw a sprite M0 with a color replaced -extern void cpct_drawSpriteColorizeM0(u8* sprite, u8* destMem, u8 width, u8 height) __z88dk_callee; -extern void cpct_drawSpriteMaskedColorizeM0(u8* sprite, u8* destMem, u8 width, u8 height) __z88dk_callee; -extern void cpct_drawSpriteMaskedAlignedColorizeM0(u8* sprite, u8* destMem, u8 width, u8 height, const u8* maskTable) __z88dk_callee; +extern void cpct_drawSpriteColorizeM0(u8* sprite, u8* destMem, u8 width, u8 height, u8 oldColor, u8 newColor) __z88dk_callee; +extern void cpct_drawSpriteMaskedColorizeM0(u8* sprite, u8* destMem, u8 width, u8 height, u8 oldColor, u8 newColor) __z88dk_callee; +extern void cpct_drawSpriteMaskedAlignedColorizeM0(u8* sprite, u8* destMem, u8 width, u8 height, u8 oldColor, u8 newColor, const u8* maskTable) __z88dk_callee; // Functions to replace a color in sprite M1 -extern void cpct_spriteColorizeM1(u8* sprite, u8* spriteColor, u8 width, u8 height) __z88dk_callee; +extern void cpct_spriteColorizeM1(u8* sprite, u8* spriteColor, u8 width, u8 height, u8 oldColor, u8 newColor) __z88dk_callee; extern void cpct_spriteMaskedColorizeM1(u8* sprite, u8* spriteColor, u8 width, u8 height, u8 oldColor, u8 newColor) __z88dk_callee; // Functions to draw a sprite M1 with a color replaced diff --git a/examples/medium/colorReplace/src/drawing.c b/examples/medium/colorReplace/src/drawing.c index aa02f4f8a..414450594 100644 --- a/examples/medium/colorReplace/src/drawing.c +++ b/examples/medium/colorReplace/src/drawing.c @@ -1,8 +1,8 @@ //-----------------------------LICENSE NOTICE------------------------------------ // This file is part of CPCtelera: An Amstrad CPC Game Engine -// Copyright (C) 2017 Bouche Arnaud -// Copyright (C) 2017 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) +// Copyright (C) 2018 Bouche Arnaud (@Arnaud6128) +// Copyright (C) 2018 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR) // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Lesser General Public License as published by @@ -22,107 +22,104 @@ ///////////////////////////////////////////////////////////////////////////////// // GLOBAL VARIABLES -u8 gSpriteColorized[G_BALOON_W*G_BALOON_H]; // Array for sprite to color -u8 gBackGroundColor; // Background color -u8 gBaloonColor; // Current color baloon -u8 gPosCloud; // Position of cloude +u8 gSpriteColorized[G_BALOON_W*G_BALOON_H]; // Array for sprite to color +u8 gBackGroundColor; // Background color +u8 gBaloonColor; // Current color baloon +u8 gPosCloud; // Position of cloude ///////////////////////////////////////////////////////////////////////////////// // STRUCTURES DEFINITION -typedef struct TBaloon // Baloon structure +typedef struct TBaloon // Baloon structure { - i16 posY; // Absolute Baloon PosY (can be outside screen) - u8 posX; // Absolute Baloon PosX - - u8 drawPosY; // In screen Baloon PosY - u8 drawCY; // In screen Baloon Height - - u8 speed; // Baloon speed - u8 color; // Baloon color drawn - - u8 status; // Baloon status ACTIVE / INACTIVE + i16 posY; // Absolute Baloon PosY (can be outside screen) + u8 posX; // Absolute Baloon PosX + + u8 drawPosY; // In screen Baloon PosY + u8 drawCY; // In screen Baloon Height + + u8 speed; // Baloon speed + u8 color; // Baloon color drawn + + u8 status; // Baloon status ACTIVE / INACTIVE } SBaloon; -typedef struct TBaloons // All baloons structure +typedef struct TBaloons // All baloons structure { - u8 nb; // Nb baloons in screen - SBaloon baloons[NB_BALOONS]; // Array of baloon + u8 nb; // Nb baloons in screen + SBaloon baloons[NB_BALOONS]; // Array of baloon } SBaloons; -SBaloons gBaloons; // Baloons to draw +SBaloons gBaloons; // Baloons to draw -typedef struct TStar // Lighting star structure +typedef struct TStar // Lighting star structure { - u8 posX; // Screen PosX - u8 posY; // Screen PosY + u8 posX; // Screen PosX + u8 posY; // Screen PosY - u8 color; // Star color drawn + u8 color; // Star color drawn } SStar; -typedef struct TStars // All stars structure +typedef struct TStars // All stars structure { - SStar stars[NB_STARS]; // Array of stars + SStar stars[NB_STARS]; // Array of stars } SStars; -SStars gStars; // Stars to draw +SStars gStars; // Stars to draw /////////////////////////////////////////////////////// -/// GET RANDOM FROM 0 TO MAX-1 +/// GET RANDOM FROM 0 TO MAX-1 /// u8 GetRand(u8 max) { - return cpct_rand()%max; + return cpct_rand()%max; } /////////////////////////////////////////////////////// -/// CHANGE TWO COLORS OF BALOON SPRITE +/// CHANGE TWO COLORS OF BALOON SPRITE /// void ColorSprite(u8 color) { - // Replace the two colors 1 and 2 of sprite baloon - cpct_setReplaceColorsM0(1, color); - cpct_spriteColorizeM0(g_baloon, gSpriteColorized, G_BALOON_W, G_BALOON_H); // Colors are consecutives - - cpct_setReplaceColorsM0(2, color + 1); - cpct_spriteColorizeM0(gSpriteColorized, gSpriteColorized, G_BALOON_W, G_BALOON_H); + // Replace the two colors 1 and 2 of sprite baloon + cpct_spriteColorizeM0(g_baloon, gSpriteColorized, G_BALOON_W, G_BALOON_H, 1, color); // Colors are consecutives + cpct_spriteColorizeM0(gSpriteColorized, gSpriteColorized, G_BALOON_W, G_BALOON_H, 2, color + 1); } /////////////////////////////////////////////////////// -/// CLEAR BALOON BACKGROUND +/// CLEAR BALOON BACKGROUND /// void ClearBaloon(SBaloon* baloon) { - // If baloon in visible part of view - if (baloon->drawPosY < VIEW_DOWN) - { - u8* pvmem; - - // Compute size to be filled with background color - u8 clearCY = baloon->drawCY + BALOON_TRAIL; - - // Compute position to clear - u8 posDownClearY = baloon->drawPosY + clearCY; - if (posDownClearY > VIEW_DOWN) - clearCY = VIEW_DOWN - baloon->drawPosY; - - // Draw the box with background color to clear - pvmem = GetBackBufferPtr(baloon->posX, baloon->drawPosY); - cpct_drawSolidBox(pvmem, gBackGroundColor, G_BALOON_W, clearCY); - } + // If baloon in visible part of view + if (baloon->drawPosY < VIEW_DOWN) + { + u8* pvmem; + + // Compute size to be filled with background color + u8 clearCY = baloon->drawCY + BALOON_TRAIL; + + // Compute position to clear + u8 posDownClearY = baloon->drawPosY + clearCY; + if (posDownClearY > VIEW_DOWN) + clearCY = VIEW_DOWN - baloon->drawPosY; + + // Draw the box with background color to clear + pvmem = GetBackBufferPtr(baloon->posX, baloon->drawPosY); + cpct_drawSolidBox(pvmem, gBackGroundColor, G_BALOON_W, clearCY); + } } /////////////////////////////////////////////////////// -/// DELETE BALOON +/// DELETE BALOON /// void DeleteBaloons(SBaloon* baloons, SBaloon* baloonToDel, u8* nb) { - // Get last baloon in array - // Decrement number of remaining baloons in array - const SBaloon* lastBaloon = &baloons[--*nb]; - - // Replace baloon to be deleted with last baloon (if they are not the same) - if (baloonToDel != lastBaloon) - cpct_memcpy(baloonToDel, lastBaloon, sizeof(SBaloon)); + // Get last baloon in array + // Decrement number of remaining baloons in array + const SBaloon* lastBaloon = &baloons[--*nb]; + + // Replace baloon to be deleted with last baloon (if they are not the same) + if (baloonToDel != lastBaloon) + cpct_memcpy(baloonToDel, lastBaloon, sizeof(SBaloon)); } /////////////////////////////////////////////////////// @@ -130,85 +127,85 @@ void DeleteBaloons(SBaloon* baloons, SBaloon* baloonToDel, u8* nb) /// void UpdateBaloons() { - SBaloon* itBaloon = gBaloons.baloons; - u8 i; - - // Test if we can add a new baloon - if (gBaloons.nb < NB_BALOONS) - { - // Add new baloon at end of array - // Increment number of baloons in array - SBaloon* newBaloon = &gBaloons.baloons[gBaloons.nb++]; - - // Get random positions X and Y - newBaloon->posX = GetRand(SCREEN_CX - G_BALOON_W); - newBaloon->posY = SCREEN_CY - GetRand(40); - - // Get random speed - newBaloon->speed = GetRand(3) + 2; - - // Get circular next color 2 by 2 until 12 - gBaloonColor = (gBaloonColor + 2) % 12; - newBaloon->color = gBaloonColor + 1; - - // Set baloon ACTIVE - newBaloon->status = BALOON_ACTIVE; - } - - // Update all baloons - for (i = 0; i < gBaloons.nb; i++) - { - // If baloon active move and draw it - if (itBaloon->status == BALOON_ACTIVE) - { - // Test if whole baloon outside view - if (itBaloon->posY + G_BALOON_H < VIEW_TOP) - { - // Set baloon inactive - itBaloon->status = BALOON_INACTIVE; - // Clear baloon background - ClearBaloon(itBaloon); - } - else - { - // Move baloon to up according its speed - i16 posY = itBaloon->posY - itBaloon->speed; - itBaloon->posY = posY; + SBaloon* itBaloon = gBaloons.baloons; + u8 i; + + // Test if we can add a new baloon + if (gBaloons.nb < NB_BALOONS) + { + // Add new baloon at end of array + // Increment number of baloons in array + SBaloon* newBaloon = &gBaloons.baloons[gBaloons.nb++]; + + // Get random positions X and Y + newBaloon->posX = GetRand(SCREEN_CX - G_BALOON_W); + newBaloon->posY = SCREEN_CY - GetRand(40); + + // Get random speed + newBaloon->speed = GetRand(3) + 2; + + // Get circular next color 2 by 2 until 12 + gBaloonColor = (gBaloonColor + 2) % 12; + newBaloon->color = gBaloonColor + 1; + + // Set baloon ACTIVE + newBaloon->status = BALOON_ACTIVE; + } + + // Update all baloons + for (i = 0; i < gBaloons.nb; i++) + { + // If baloon active move and draw it + if (itBaloon->status == BALOON_ACTIVE) + { + // Test if whole baloon outside view + if (itBaloon->posY + G_BALOON_H < VIEW_TOP) + { + // Set baloon inactive + itBaloon->status = BALOON_INACTIVE; + // Clear baloon background + ClearBaloon(itBaloon); + } + else + { + // Move baloon to up according its speed + i16 posY = itBaloon->posY - itBaloon->speed; + itBaloon->posY = posY; - // Baloon outside view by top - if (posY < VIEW_TOP) - { - itBaloon->drawPosY = 0; - itBaloon->drawCY = G_BALOON_H + posY; - } - else - // Baloon outside view by down - if (posY + G_BALOON_H > VIEW_DOWN) - { - itBaloon->drawPosY = posY; - itBaloon->drawCY = VIEW_DOWN - posY; - } - // Baloon all in view - else - { - itBaloon->drawPosY = posY; - itBaloon->drawCY = G_BALOON_H; - } - } - } - // If inactive delete baloon - else - { - // Clear baloon background - ClearBaloon(itBaloon); - - // Delete baloon from list - DeleteBaloons(gBaloons.baloons, itBaloon, &gBaloons.nb); - } - - // Get next baloon pointer - itBaloon++; - } + // Baloon outside view by top + if (posY < VIEW_TOP) + { + itBaloon->drawPosY = 0; + itBaloon->drawCY = G_BALOON_H + posY; + } + else + // Baloon outside view by down + if (posY + G_BALOON_H > VIEW_DOWN) + { + itBaloon->drawPosY = posY; + itBaloon->drawCY = VIEW_DOWN - posY; + } + // Baloon all in view + else + { + itBaloon->drawPosY = posY; + itBaloon->drawCY = G_BALOON_H; + } + } + } + // If inactive delete baloon + else + { + // Clear baloon background + ClearBaloon(itBaloon); + + // Delete baloon from list + DeleteBaloons(gBaloons.baloons, itBaloon, &gBaloons.nb); + } + + // Get next baloon pointer + itBaloon++; + } } /////////////////////////////////////////////////////// @@ -216,27 +213,27 @@ void UpdateBaloons() /// void DrawBaloon(SBaloon* baloon, const u8* spriteBaloon) { - i16 posY = baloon->posY; - - // If baloon in view - if (posY + G_BALOON_H > VIEW_TOP && posY < VIEW_DOWN) - { - // Get VMem pointer of current baloon position - u8* pvmem = GetBackBufferPtr(baloon->posX, baloon->drawPosY); - const u8* sprite = (u8*)spriteBaloon; - - // Baloon partialy outside view by top - if (posY < VIEW_TOP) - { - // Compute Y position - u8 y = -posY; - - // Compute sprite offset - sprite = (u8*)spriteBaloon + G_BALOON_W * y; - } - - cpct_drawSpriteMaskedAlignedTable(sprite, pvmem, G_BALOON_W, baloon->drawCY, gMaskTable); - } + i16 posY = baloon->posY; + + // If baloon in view + if (posY + G_BALOON_H > VIEW_TOP && posY < VIEW_DOWN) + { + // Get VMem pointer of current baloon position + u8* pvmem = GetBackBufferPtr(baloon->posX, baloon->drawPosY); + const u8* sprite = (u8*)spriteBaloon; + + // Baloon partialy outside view by top + if (posY < VIEW_TOP) + { + // Compute Y position + u8 y = -posY; + + // Compute sprite offset + sprite = (u8*)spriteBaloon + G_BALOON_W * y; + } + + cpct_drawSpriteMaskedAlignedTable(sprite, pvmem, G_BALOON_W, baloon->drawCY, gMaskTable); + } } /////////////////////////////////////////////////////// @@ -244,45 +241,42 @@ void DrawBaloon(SBaloon* baloon, const u8* spriteBaloon) /// void DrawStars() { - // Static stars color - const static u8 sColorStar[NB_COLORS_STAR] = { 2, 4, 7, 8, 10, 11, 12 }; - static u8 color = 0; - - u8 i; - for (i = 0; i < NB_STARS; i++) - { - // Get video pointer of each star to be drawn - u8* pvmem = GetBackBufferPtr(gStars.stars[i].posX, gStars.stars[i].posY); - u8 color = gStars.stars[i].color++; - - // Set color to change - cpct_setReplaceColorsM0(15, sColorStar[color]); - - // Use different drawing color methods - if (i < NB_STARS/3) - { - // Color and draw masked sprite in video memory - cpct_drawSpriteMaskedColorizeM0(g_star_trans, pvmem, G_STAR_TRANS_W, G_STAR_TRANS_H); - } - else if (i > NB_STARS/3 && i < 2*NB_STARS/3) - { - // Color and draw masked aligned sprite in video memory - cpct_drawSpriteMaskedAlignedColorizeM0(g_square, pvmem, G_SQUARE_W, G_SQUARE_H, gMaskTable); - } - else - { - // Color and copy masked sprite in temporary array - u8 circleColor[G_CIRCLE_TRANS_W * G_CIRCLE_TRANS_H * 2]; - cpct_spriteMaskedColorizeM0(g_circle_trans, circleColor, G_CIRCLE_TRANS_W, G_CIRCLE_TRANS_H); - - // Draw masked Sprite from temporary array - cpct_drawSpriteMasked(circleColor, pvmem, G_CIRCLE_TRANS_W, G_CIRCLE_TRANS_H); - } - - // If all colors palette used restart from 0 - if (color == NB_COLORS_STAR - 1) - gStars.stars[i].color = 0; - } + // Static stars color + const static u8 sColorStar[NB_COLORS_STAR] = { 2, 4, 7, 8, 10, 11, 12 }; + static u8 color = 0; + + u8 i; + for (i = 0; i < NB_STARS; i++) + { + // Get video pointer of each star to be drawn + u8* pvmem = GetBackBufferPtr(gStars.stars[i].posX, gStars.stars[i].posY); + u8 color = gStars.stars[i].color++; + + // Use different drawing color methods + if (i < NB_STARS/3) + { + // Color and draw masked sprite in video memory + cpct_drawSpriteMaskedColorizeM0(g_star_trans, pvmem, G_STAR_TRANS_W, G_STAR_TRANS_H, 15, sColorStar[color]); + } + else if (i > NB_STARS/3 && i < 2*NB_STARS/3) + { + // Color and draw masked aligned sprite in video memory + cpct_drawSpriteMaskedAlignedColorizeM0(g_square, pvmem, G_SQUARE_W, G_SQUARE_H, 15, sColorStar[color], gMaskTable); + } + else + { + // Color and copy masked sprite in temporary array + u8 circleColor[G_CIRCLE_TRANS_W * G_CIRCLE_TRANS_H * 2]; + cpct_spriteMaskedColorizeM0(g_circle_trans, circleColor, G_CIRCLE_TRANS_W, G_CIRCLE_TRANS_H, 15, sColorStar[color]); + + // Draw masked Sprite from temporary array + cpct_drawSpriteMasked(circleColor, pvmem, G_CIRCLE_TRANS_W, G_CIRCLE_TRANS_H); + } + + // If all colors palette used restart from 0 + if (color == NB_COLORS_STAR - 1) + gStars.stars[i].color = 0; + } } /////////////////////////////////////////////////////// @@ -290,9 +284,9 @@ void DrawStars() /// void DrawCloud() { - // Draw cloud at fixed place - u8* pvmem = GetBackBufferPtr(0, POS_CLOUD_Y); - cpct_drawSprite(g_cloud, pvmem, G_CLOUD_W, G_CLOUD_H); + // Draw cloud at fixed place + u8* pvmem = GetBackBufferPtr(0, POS_CLOUD_Y); + cpct_drawSprite(g_cloud, pvmem, G_CLOUD_W, G_CLOUD_H); } /////////////////////////////////////////////////////// @@ -300,40 +294,35 @@ void DrawCloud() /// void DrawSceneBaloons() { - u8 i, color = 0; - - // Clear background for all baloons - SBaloon* itBaloon = gBaloons.baloons; // Get first baloon pointer - for (i = 0; i < gBaloons.nb; i++) - { - ClearBaloon(itBaloon); - itBaloon++; - } - - // Draw sprite cloud - DrawCloud(); - - // Draw all baloons - itBaloon = gBaloons.baloons; // Get first baloon pointer - for (i = 0; i < gBaloons.nb; i++) - { - const u8* sprite = g_baloon; // Default baloon sprite (blue) + u8 i; + + // Clear background for all baloons + SBaloon* itBaloon = gBaloons.baloons; // Get first baloon pointer + for (i = 0; i < gBaloons.nb; i++) + { + ClearBaloon(itBaloon); + itBaloon++; + } + + // Draw sprite cloud + DrawCloud(); + + // Draw all baloons + itBaloon = gBaloons.baloons; // Get first baloon pointer + for (i = 0; i < gBaloons.nb; i++) + { + const u8* sprite = g_baloon; // Default baloon sprite (blue) - // Test if sprite have colors to change - if (itBaloon->color > 1) // Color 0 (white) is transparent color - { - if (color != itBaloon->color) // Test if need to change Color of Sprite - { - color = itBaloon->color; - ColorSprite(color); // Change colors of ballon - } - - sprite = gSpriteColorized; // Sprite to draw is colorized baloon - } - - DrawBaloon(itBaloon, sprite); // Draw baloon sprite - itBaloon++; // Get next baloon - } + // Test if sprite have colors to change + if (itBaloon->color > 1) // Color 0 (white) is transparent color + { + ColorSprite(itBaloon->color); // Change colors of ballon + sprite = gSpriteColorized; // Sprite to draw is colorized baloon + } + + DrawBaloon(itBaloon, sprite); // Draw baloon sprite + itBaloon++; // Get next baloon + } } /////////////////////////////////////////////////////// @@ -341,21 +330,21 @@ void DrawSceneBaloons() /// void DrawBackground() { - u8* pvmem; - - // Fill video buffer with background color - cpct_memset((u8*)SCREEN_BUFF, gBackGroundColor, VMEM_SIZE); - - // Draw left part of Roof - pvmem = GetBackBufferPtr(0, SCREEN_CY-G_ROOF_H); - cpct_drawSprite(g_roof, pvmem, G_ROOF_W, G_ROOF_H); - - // Draw right part of Roof - pvmem += G_ROOF_W; - cpct_drawSprite(g_roof, pvmem, G_ROOF_W, G_ROOF_H); - - // Copy Same background on both buffers - cpct_memcpy(CPCT_VMEM_START, (u8*)SCREEN_BUFF, VMEM_SIZE); + u8* pvmem; + + // Fill video buffer with background color + cpct_memset((u8*)SCREEN_BUFF, gBackGroundColor, VMEM_SIZE); + + // Draw left part of Roof + pvmem = GetBackBufferPtr(0, SCREEN_CY-G_ROOF_H); + cpct_drawSprite(g_roof, pvmem, G_ROOF_W, G_ROOF_H); + + // Draw right part of Roof + pvmem += G_ROOF_W; + cpct_drawSprite(g_roof, pvmem, G_ROOF_W, G_ROOF_H); + + // Copy Same background on both buffers + cpct_memcpy(CPCT_VMEM_START, (u8*)SCREEN_BUFF, VMEM_SIZE); } ///////////////////////////////////////////////////////////////////////////////// @@ -365,18 +354,18 @@ void DrawBackground() /// void InitializeDrawing() { - u8 dx = SCREEN_CX / NB_STARS; // Compute space between stars - - u8 i; - for (i = 0; i < NB_STARS; i++) - { - gStars.stars[i].posX = dx * i + 5; // Constant space beetween stars - gStars.stars[i].posY = GetRand(10) + 175; // Random Y position from 175 to 184 - gStars.stars[i].color = GetRand(NB_COLORS_STAR); // Random color from 0 to NB_COLORS_STAR-1 - } - - gBackGroundColor = cpct_px2byteM0(14, 14); // Get byte color of background for M0 - gBaloons.nb = 0; // No baloon to draw at start - - DrawBackground(); // Set background on both buffers + u8 dx = SCREEN_CX / NB_STARS; // Compute space between stars + + u8 i; + for (i = 0; i < NB_STARS; i++) + { + gStars.stars[i].posX = dx * i + 5; // Constant space beetween stars + gStars.stars[i].posY = GetRand(10) + 175; // Random Y position from 175 to 184 + gStars.stars[i].color = GetRand(NB_COLORS_STAR); // Random color from 0 to NB_COLORS_STAR-1 + } + + gBackGroundColor = cpct_px2byteM0(14, 14); // Get byte color of background for M0 + gBaloons.nb = 0; // No baloon to draw at start + + DrawBackground(); // Set background on both buffers }