Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add functions for color replacement for sprites (M0 and M1) and example (issue #14) #69

Merged
merged 35 commits into from
Jan 28, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
87cea27
Add files via upload
Arnaud6128 Jan 19, 2018
cc8a049
Add sprite color replace functions M0 and M1
Arnaud6128 Jan 19, 2018
d0ff60a
Add header to replaceColor functions and update Sprites.h
Arnaud6128 Jan 19, 2018
61de6da
Add sprite color replace in M0 example
Arnaud6128 Jan 19, 2018
02d77cf
Merge branch 'colorreplace' of https://github.com/Arnaud6128/cpcteler…
Arnaud6128 Jan 19, 2018
0e9364a
Compilation error correction under cpctelera 1.4.2
Arnaud6128 Jan 20, 2018
81ec623
Add cpct_getScreenToSprite to header
Arnaud6128 Jan 20, 2018
bb5e416
Add cpct_getScreenToSprite function to video
Arnaud6128 Jan 20, 2018
f78f2b0
Add screen capture example
Arnaud6128 Jan 20, 2018
bfbada1
Remove useless files in example
Arnaud6128 Jan 20, 2018
8effe52
Add extern keyword to functions in colorreplace header
Arnaud6128 Jan 20, 2018
242164f
Add sprites generation directory
Arnaud6128 Jan 20, 2018
35a944a
Modify commentaries
Arnaud6128 Jan 20, 2018
4c60a75
Update cpct_getScreenToSprite.asm
Arnaud6128 Jan 20, 2018
9712ffc
Review getScreenToSprite code example
lronaldo Jan 20, 2018
ae535ce
Completing review of getScreenToSprite example
lronaldo Jan 20, 2018
6463716
Added gitignore for generated sprites
lronaldo Jan 20, 2018
b3e7994
Improved getScreenToSprite implementation
lronaldo Jan 20, 2018
03112b7
Merge branch 'Arnaud6128-readvideomem' into readvideomem
lronaldo Jan 20, 2018
c71041e
Moved getScreenToSprite to sprites/screenToSprite
lronaldo Jan 20, 2018
03f1eb3
Using spaces instead of tabs for indenting
Arnaud6128 Jan 20, 2018
83a7d88
Replace tabs with spaces in coloreplace asm
Arnaud6128 Jan 20, 2018
3eb3297
Merge branch 'colorreplace' of https://github.com/Arnaud6128/cpcteler…
lronaldo Jan 26, 2018
74f3eaa
Better include form for cpct_undocumentedOpcodes
lronaldo Jan 26, 2018
04a3424
Add new function cpct_setReplaceColors and update others
Arnaud6128 Jan 26, 2018
07a0981
Added new asm macro for accessing Look-Up-Tables
lronaldo Jan 26, 2018
2821498
Modified allmacros.h.s to properly include luts
lronaldo Jan 27, 2018
f113038
Created fast split version of spriteColourizeM0
lronaldo Jan 27, 2018
8426f25
Added new functions to colorReplace.h
lronaldo Jan 27, 2018
be68a92
Added gitignore to colorReplace example
lronaldo Jan 27, 2018
6d08814
Used new functions in the example
lronaldo Jan 27, 2018
869a54a
Revert "Add new function cpct_setReplaceColors and update others"
Arnaud6128 Jan 27, 2018
e5346e7
Add new function cpct_setReplaceColors and update others
Arnaud6128 Jan 26, 2018
18582c4
Revert "Add new function cpct_setReplaceColors and update others"
Arnaud6128 Jan 27, 2018
8bc6eaa
Merge branch 'colorreplace' of https://github.com/Arnaud6128/cpcteler…
Arnaud6128 Jan 27, 2018
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions cpctelera/src/macros/allmacros.h.s
Original file line number Diff line number Diff line change
Expand Up @@ -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_luts.h.s"

;;//////////////////////////////////////////////////////////////////////
;; Group: General Useful Macros
Expand Down
79 changes: 79 additions & 0 deletions cpctelera/src/macros/cpct_luts.h.s
Original file line number Diff line number Diff line change
@@ -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

203 changes: 203 additions & 0 deletions cpctelera/src/sprites/colorReplace/M0/cpct_drawSpriteColorizeM0.asm
Original file line number Diff line number Diff line change
@@ -0,0 +1,203 @@
;;-----------------------------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_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


Original file line number Diff line number Diff line change
@@ -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.h.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
Original file line number Diff line number Diff line change
@@ -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.h.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
Loading