Difference between revisions of "Programming:Convert CPC sprites to Plus hardware sprites"
(→Source code) |
|||
(11 intermediate revisions by one other user not shown) | |||
Line 1: | Line 1: | ||
− | The Plus hardware sprite format is different to the standard CPC sprite format, so sprites have to be converted if you want to use them as hardware sprites on the Plus. | + | The Plus [[ASIC]] hardware sprite format is different to the standard CPC sprite format, so sprites have to be converted if you want to use them as hardware sprites on the Plus. |
== The formats == | == The formats == | ||
− | Plus hardware sprites are 16x16 pixels in size and have 16 colours, with | + | Plus hardware sprites are 16x16 pixels in size and have 16 colours, with PEN 0 always being transparent. Therefore, when converting standard CPC sprites it is easiest to convert them from MODE 0 because this mode supports a colour depth of 16 and two pixels are stored in one byte. |
− | The pixel data on the standard CPC is stored in an awkward manner and a byte is organised as follows: | + | The pixel data in MODE 0 on the standard CPC is stored in an awkward manner and a byte is organised as follows: |
[[File:Pixels.png]] | [[File:Pixels.png]] | ||
Line 20: | Line 20: | ||
== Conversion == | == Conversion == | ||
− | To convert a sprite, you can | + | To convert a sprite, you can download the DSK image below which contains a converter utility (use RUN"DISC") or you can use the source code provided on this page. |
− | To use the converter utility, you must have first | + | To use the converter utility, you must have first captured your standard CPC sprite (you can use the SPRITER utility on the disc to do this) which must be 16 x 16 in size (8 bytes wide by 16 lines high). The converter utility will then display the original and converted sprite before saving the converted sprite to the disk. |
== Download == | == Download == | ||
Line 30: | Line 30: | ||
== Source code == | == Source code == | ||
− | The source code for the converter (which will assemble in | + | The source code for the converter (which will assemble in [[WinApe]] and [[Maxam]]) is as follows: |
+ | <pre> | ||
<geshi lang=Z80> | <geshi lang=Z80> | ||
;Convert CPC sprite to Plus sprite | ;Convert CPC sprite to Plus sprite | ||
Line 37: | Line 38: | ||
;Public Domain | ;Public Domain | ||
− | org & | + | org &8000 |
ld b,16 ;loop counter, sprite is 16 lines high | ld b,16 ;loop counter, sprite is 16 lines high | ||
Line 60: | Line 61: | ||
ld a,(hl) ;and load data from it into A | ld a,(hl) ;and load data from it into A | ||
− | bit 7,a ;does bit | + | bit 7,a ;does bit equal 1? if so, reset Z |
ld b,&1 ;pixel 0, bit 0 = &1 | ld b,&1 ;pixel 0, bit 0 = &1 | ||
− | call nz,addbit ; | + | call nz,addbit ;add the bit to our pixel |
− | bit 3,a ;does bit | + | bit 3,a ;does bit equal 1? if so, reset Z |
ld b,&2 ;pixel 0, bit 1 (%0010) = &2 | ld b,&2 ;pixel 0, bit 1 (%0010) = &2 | ||
− | call nz,addbit ; | + | call nz,addbit ;add the bit to our pixel |
− | bit 5,a ;does bit | + | bit 5,a ;does bit equal 1? if so, reset Z |
ld b,&4 ;pixel 0, bit 2 (%0100) = &4 | ld b,&4 ;pixel 0, bit 2 (%0100) = &4 | ||
− | call nz,addbit ; | + | call nz,addbit ;add the bit to our pixel |
− | bit 1,a ;does bit | + | bit 1,a ;does bit equal 1? if so, reset Z |
ld b,&8 ;pixel 0, bit 3 (%1000) = &8 | ld b,&8 ;pixel 0, bit 3 (%1000) = &8 | ||
− | call nz,addbit ; | + | call nz,addbit ;add the bit to our pixel |
call storeit ;store pixel at sprite address | call storeit ;store pixel at sprite address | ||
Line 84: | Line 85: | ||
ld a,(hl) ;and load it into A | ld a,(hl) ;and load it into A | ||
− | bit 6,a ;does bit | + | bit 6,a ;does bit equal 1? if so, reset Z |
ld b,&1 ;pixel 1, bit 0 (%0001) = &1 | ld b,&1 ;pixel 1, bit 0 (%0001) = &1 | ||
− | call nz,addbit ; | + | call nz,addbit ;add the bit to our pixel |
− | bit 2,a ;does bit | + | bit 2,a ;does bit equal 1? if so, reset Z |
ld b,&2 ;pixel 1, bit 1 (%0010) = &2 | ld b,&2 ;pixel 1, bit 1 (%0010) = &2 | ||
− | call nz,addbit ; | + | call nz,addbit ;add the bit to our pixel |
− | bit 4,a ;does bit | + | bit 4,a ;does bit equal 1? if so, reset Z |
ld b,&4 ;pixel 1, bit 2 (%0100) = &4 | ld b,&4 ;pixel 1, bit 2 (%0100) = &4 | ||
− | call nz,addbit ; | + | call nz,addbit ;add the bit to our pixel |
− | bit 0,a ;does bit | + | bit 0,a ;does bit equal 1? if so, reset Z |
ld b,&8 ;pixel 1, bit 3 (%1000) = &8 | ld b,&8 ;pixel 1, bit 3 (%1000) = &8 | ||
− | call nz,addbit ; | + | call nz,addbit ;add the bit to our pixel |
call storeit ;store pixel at sprite address | call storeit ;store pixel at sprite address | ||
Line 140: | Line 141: | ||
ret | ret | ||
− | scraddr: dw &C000 | + | scraddr: dw &C000 ;screen address to grab CPC sprite from |
− | pixel: db &0 | + | pixel: db &0 ;pixel store |
− | spraddr: dw &9000 | + | spraddr: dw &9000 ;address Plus sprite is stored (&100 bytes in length) |
</geshi> | </geshi> | ||
+ | </pre> | ||
== See also == | == See also == |
Latest revision as of 01:49, 15 May 2013
The Plus ASIC hardware sprite format is different to the standard CPC sprite format, so sprites have to be converted if you want to use them as hardware sprites on the Plus.
The formats
Plus hardware sprites are 16x16 pixels in size and have 16 colours, with PEN 0 always being transparent. Therefore, when converting standard CPC sprites it is easiest to convert them from MODE 0 because this mode supports a colour depth of 16 and two pixels are stored in one byte.
The pixel data in MODE 0 on the standard CPC is stored in an awkward manner and a byte is organised as follows:
The top row shows the two pixels and the bottom row shows how they are arranged in one byte on the standard CPC.
The pixel data on the Plus is organised in a straight forward manner being that each byte is a pixel and its value is the PEN colour. For example, the first two lines of a Plus sprite could be:
<geshi lang=Z80> 00,01,02,03,04,05,06,07,08,09,10,11,12,13,14,15 01,02,03,04,05,06,07,08,09,10,11,12,13,14,15,00 </geshi>
Conversion
To convert a sprite, you can download the DSK image below which contains a converter utility (use RUN"DISC") or you can use the source code provided on this page.
To use the converter utility, you must have first captured your standard CPC sprite (you can use the SPRITER utility on the disc to do this) which must be 16 x 16 in size (8 bytes wide by 16 lines high). The converter utility will then display the original and converted sprite before saving the converted sprite to the disk.
Download
Media:Convspr.dsk - DSK image containing the converter utility
Source code
The source code for the converter (which will assemble in WinApe and Maxam) is as follows:
<geshi lang=Z80> ;Convert CPC sprite to Plus sprite ;by Redbox, February 2010 ;Public Domain org &8000 ld b,16 ;loop counter, sprite is 16 lines high mainloop: push bc ;preserve loop counter call doline ld hl,(scraddr) ;load HL with screen address call nextline ;work out next screen line down ld (scraddr),hl ;and store the screen address pop bc ;restore loop counter djnz mainloop ;decrease B and jump back to loop if not 0 ret ;exit doline: ld b,8 ;loop counter, sprite is 8 bytes wide = 16 pixels lineloop: push bc ;store counter ld hl,(scraddr) ;get screen location ld a,(hl) ;and load data from it into A bit 7,a ;does bit equal 1? if so, reset Z ld b,&1 ;pixel 0, bit 0 = &1 call nz,addbit ;add the bit to our pixel bit 3,a ;does bit equal 1? if so, reset Z ld b,&2 ;pixel 0, bit 1 (%0010) = &2 call nz,addbit ;add the bit to our pixel bit 5,a ;does bit equal 1? if so, reset Z ld b,&4 ;pixel 0, bit 2 (%0100) = &4 call nz,addbit ;add the bit to our pixel bit 1,a ;does bit equal 1? if so, reset Z ld b,&8 ;pixel 0, bit 3 (%1000) = &8 call nz,addbit ;add the bit to our pixel call storeit ;store pixel at sprite address ld a,&0 ;reset pixel ld (pixel),a ;and store reset ld hl,(scraddr) ;get data from current screen location ld a,(hl) ;and load it into A bit 6,a ;does bit equal 1? if so, reset Z ld b,&1 ;pixel 1, bit 0 (%0001) = &1 call nz,addbit ;add the bit to our pixel bit 2,a ;does bit equal 1? if so, reset Z ld b,&2 ;pixel 1, bit 1 (%0010) = &2 call nz,addbit ;add the bit to our pixel bit 4,a ;does bit equal 1? if so, reset Z ld b,&4 ;pixel 1, bit 2 (%0100) = &4 call nz,addbit ;add the bit to our pixel bit 0,a ;does bit equal 1? if so, reset Z ld b,&8 ;pixel 1, bit 3 (%1000) = &8 call nz,addbit ;add the bit to our pixel call storeit ;store pixel at sprite address ld a,&0 ;reset pixel ld (pixel),a ;and store reset ld hl,(scraddr) ;get screen address inc hl ;increase it ld (scraddr),hl ;store it for next time pop bc ;restore loop counter djnz lineloop ;decrease B and jump back to loop if not 0 ret ;else return addbit: push af ;preserve screen data ld a,(pixel) ;load A with pixel add b ;add what we've found to it ld (pixel),a ;store it again pop af ;restore screen data ret storeit: ld hl,(spraddr) ;load HL with sprite address ld a,(pixel) ;load pixel into A ld (hl),a ;load sprite address with pixel value inc hl ;increase sprite address ld (spraddr),hl ;and store it for next time ret nextline: ld a,l ;load A with L (low byte of screen address) sub 8 ;subtract the 8 bytes we've already done ld l,a ;and load it back into L ld a,8 ;load A with 8 add a,h ;which means we add &800 for the next pixel line down ld h,a ;write new address back to H ret nc ;and return if no overflow ld de,&C050 ;else loop back round to top of screen plus one pixel line add hl,de ;by adding &C000+&50 to HL ret scraddr: dw &C000 ;screen address to grab CPC sprite from pixel: db &0 ;pixel store spraddr: dw &9000 ;address Plus sprite is stored (&100 bytes in length) </geshi>