258 lines
12 KiB
NASM
258 lines
12 KiB
NASM
|
;;================================================================================================;;
|
||
|
;;//// z80.asm //// (c) Nable, 2007-2008 /////////////////////////////////////////////////////////;;
|
||
|
;;================================================================================================;;
|
||
|
;; ;;
|
||
|
;; This file is part of Common development libraries (Libs-Dev). ;;
|
||
|
;; ;;
|
||
|
;; Libs-Dev 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 2.1 ;;
|
||
|
;; of the License, or (at your option) any later version. ;;
|
||
|
;; ;;
|
||
|
;; Libs-Dev 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 Libs-Dev. ;;
|
||
|
;; If not, see <http://www.gnu.org/licenses/>. ;;
|
||
|
;; ;;
|
||
|
;;================================================================================================;;
|
||
|
;; ;;
|
||
|
;; References: ;;
|
||
|
;; 1. ;;
|
||
|
;; ;;
|
||
|
;;================================================================================================;;
|
||
|
|
||
|
include 'z80.inc'
|
||
|
|
||
|
;;================================================================================================;;
|
||
|
proc img.is.z80 _data, _length ;//////////////////////////////////////////////////////////////////;;
|
||
|
;;------------------------------------------------------------------------------------------------;;
|
||
|
;? Determine if raw data could be decoded (is in z80 screen format) ;;
|
||
|
;;------------------------------------------------------------------------------------------------;;
|
||
|
;> _data = raw data as read from file/stream ;;
|
||
|
;> _length = data length ;;
|
||
|
;;------------------------------------------------------------------------------------------------;;
|
||
|
;< eax = false / true ;;
|
||
|
;;================================================================================================;;
|
||
|
xor eax,eax
|
||
|
cmp [_length],6929
|
||
|
setz al
|
||
|
je @f
|
||
|
cmp [_length],6912
|
||
|
setz al
|
||
|
@@:
|
||
|
ret
|
||
|
endp
|
||
|
|
||
|
;;================================================================================================;;
|
||
|
proc img.decode.z80 _data, _length ;//////////////////////////////////////////////////////////////;;
|
||
|
;;------------------------------------------------------------------------------------------------;;
|
||
|
;? Decode data into image if it contains correctly formed raw data in z80 screen format ;;
|
||
|
;;------------------------------------------------------------------------------------------------;;
|
||
|
;> _data = raw data as read from file/stream ;;
|
||
|
;> _length = data length ;;
|
||
|
;;------------------------------------------------------------------------------------------------;;
|
||
|
;< eax = 0 (error) or pointer to image ;;
|
||
|
;;================================================================================================;;
|
||
|
;---------------------------------------------------------------------------------------------------
|
||
|
;During the decoding:
|
||
|
;bl - PixelLeft (this means how much pixels left to put in current string)
|
||
|
;bh - CurrentString
|
||
|
;High half of ebx - use DualStos (two frames per one pixel_write)
|
||
|
;cl - PixelColorIndexInPalette
|
||
|
;ch - BackgroundColorIndexInPalette
|
||
|
;High half of ecx - blinking flag
|
||
|
;edx - address of current attribute byte
|
||
|
;---------------------------------------------------------------------------------------------------
|
||
|
locals
|
||
|
frame1 dd ?
|
||
|
OffsetIn2ndFrame dd ?
|
||
|
endl
|
||
|
xor eax,eax
|
||
|
pushad
|
||
|
cld ;paranoia
|
||
|
stdcall img.create,256,192,Image.bpp8
|
||
|
test eax,eax
|
||
|
jz img.decode.z80.locret ;test if allocation failed
|
||
|
mov [frame1],eax
|
||
|
mov esi,z80._._16color_palette
|
||
|
mov ecx,16
|
||
|
mov edi,[eax+Image.Palette]
|
||
|
rep movsd ;write palette for the first frame
|
||
|
mov esi,[_data]
|
||
|
cmp [_length],6929
|
||
|
jne @f
|
||
|
add esi,17 ;in case of 6929 byte files we just skip the info in the begininning.
|
||
|
@@:
|
||
|
;---------------------------------------------------------------------------------------------------
|
||
|
;At first we'll determine if there are any blinking pixels
|
||
|
;if no - we'll produce statical single image
|
||
|
mov ecx,768
|
||
|
lea edx,[esi+6912-768];edx points to attribute area
|
||
|
xor ebx,ebx ;begin from <0,0> (for further decoding)
|
||
|
@@:
|
||
|
test byte[edx+ecx-1],z80.BlinkFlag ;such addressing is a good optimisation
|
||
|
;(as I hope), edx is unchanged
|
||
|
jnz .decode_z80_with_blinking
|
||
|
loop @b
|
||
|
.decode_z80_without_blinking:
|
||
|
jmp .decode_z80_main_stage
|
||
|
|
||
|
.decode_z80_with_blinking:
|
||
|
or ebx,0xFFFF0000 ;use DualStos
|
||
|
mov ecx,eax ;eax still points to the first frame
|
||
|
stdcall img.create,256,192,Image.bpp8
|
||
|
test eax,eax
|
||
|
jz img.decode.z80.failed
|
||
|
mov [eax+Image.Previous],ecx
|
||
|
mov [ecx+Image.Next],eax
|
||
|
mov esi,z80._._16color_palette
|
||
|
mov ecx,16
|
||
|
mov edi,[eax+Image.Palette]
|
||
|
rep movsd ;write palette for the second frame
|
||
|
mov eax,[eax+Image.Data]
|
||
|
mov [OffsetIn2ndFrame],eax
|
||
|
;-------------------------------------------------------------------------------
|
||
|
.decode_z80_main_stage:
|
||
|
;2nd stage - convert z80 screen to 8bpp image with palette
|
||
|
.decode_z80_main_stage_main_loop:
|
||
|
test bl,7
|
||
|
jnz .decode_z80_main_stage_put_now
|
||
|
|
||
|
._z80_update_attributes:
|
||
|
movsx ecx,byte[edx] ;note that BlinkFlag is the highest bit in attribute
|
||
|
;byte, so ecx's highest bit is set automatically
|
||
|
shl ecx,5
|
||
|
shr cl,5
|
||
|
and ch,0xF
|
||
|
test ch,1000b
|
||
|
jz @f
|
||
|
or ecx,1000b ;it has the same size with 'or cl,1000b' but could be faster
|
||
|
@@:
|
||
|
inc edx
|
||
|
|
||
|
lodsb
|
||
|
mov ah,al
|
||
|
|
||
|
.decode_z80_main_stage_put_now:
|
||
|
shl ah,1
|
||
|
;-------------------------------------------------------------------------------
|
||
|
._z80_put_pixel:
|
||
|
;In: CF - put pixel with color CL, !CF - pixel with color CH
|
||
|
;High parts of ebx and ecx - as described above
|
||
|
mov al,cl ;'mov' doesn't affect flags
|
||
|
jc @f
|
||
|
mov al,ch
|
||
|
@@:
|
||
|
stosb ;'stosb' doesn't affect flags
|
||
|
|
||
|
test ebx,ebx
|
||
|
jns @f
|
||
|
test ecx,ecx
|
||
|
jns .1
|
||
|
mov al,ch
|
||
|
.1:
|
||
|
xchg [OffsetIn2ndFrame],edi
|
||
|
stosb
|
||
|
xchg [OffsetIn2ndFrame],edi
|
||
|
@@:
|
||
|
inc bl ;next pixel
|
||
|
jz .decode_z80_main_stage_row_finished
|
||
|
jmp .decode_z80_main_stage_main_loop
|
||
|
;-------------------------------------------------------------------------------
|
||
|
.decode_z80_main_stage_row_finished:
|
||
|
cmp bh,191 ;is image finished?
|
||
|
jb .decode_z80_main_stage_image_not_finished ;no.
|
||
|
.decode_z80_finish:
|
||
|
jmp .locret ;now really finished
|
||
|
;-------------------------------------------------------------------------------
|
||
|
;or not finished yet. Branch according to a row number (see documentation)
|
||
|
.decode_z80_main_stage_next_third:
|
||
|
sub bh,7
|
||
|
sub edi,256*(8-1)
|
||
|
jmp .decode_z80_main_stage_main_loop
|
||
|
|
||
|
.decode_z80_main_stage_image_not_finished:
|
||
|
;next row
|
||
|
add bh,8 ;refer to documentation
|
||
|
add edi,256*(8-1)
|
||
|
|
||
|
;if finished row is 63 or 127 then we process next third of the image
|
||
|
cmp bh,63+8
|
||
|
je .decode_z80_main_stage_next_third
|
||
|
cmp bh,127+8
|
||
|
je .decode_z80_main_stage_next_third
|
||
|
|
||
|
cmp bh,56+8 ;if finished row in [56;63) or [120;127) or [184;191)
|
||
|
jb .decode_z80_main_stage_main_loop
|
||
|
cmp bh,63+8
|
||
|
jb .4
|
||
|
cmp bh,120+8
|
||
|
jb .decode_z80_main_stage_main_loop
|
||
|
cmp bh,127+8
|
||
|
jb .4
|
||
|
cmp bh,184+8
|
||
|
jb .decode_z80_main_stage_main_loop
|
||
|
;note that if we are here then bh is < 191 (see label .2) but >= 184+8
|
||
|
.4:
|
||
|
;and if we here then bh is in [56;63) or [120;127) or [184;191)
|
||
|
sub bh,(8+56-1)
|
||
|
sub edi,256*(8+56-1)
|
||
|
sub edx,z80.AttrString*8
|
||
|
jmp .decode_z80_main_stage_main_loop
|
||
|
img.decode.z80.locret:
|
||
|
popad
|
||
|
ret
|
||
|
img.decode.z80.failed:
|
||
|
stdcall img.destroy,[frame1]
|
||
|
jmp img.decode.z80.locret
|
||
|
endp
|
||
|
|
||
|
;;================================================================================================;;
|
||
|
proc img.encode.z80 _img, _p_length ;/////////////////////////////////////////////////////////////;;
|
||
|
;;------------------------------------------------------------------------------------------------;;
|
||
|
;? Encode image into raw data in z80 screen format ;;
|
||
|
;;------------------------------------------------------------------------------------------------;;
|
||
|
;> _img = pointer to image ;;
|
||
|
;;------------------------------------------------------------------------------------------------;;
|
||
|
;< eax = 0 (error) or pointer to encoded data ;;
|
||
|
;< _p_length = encoded data length ;;
|
||
|
;;================================================================================================;;
|
||
|
xor eax, eax
|
||
|
ret
|
||
|
endp
|
||
|
|
||
|
|
||
|
;;================================================================================================;;
|
||
|
;;////////////////////////////////////////////////////////////////////////////////////////////////;;
|
||
|
;;================================================================================================;;
|
||
|
;! Below are private procs you should never call directly from your code ;;
|
||
|
;;================================================================================================;;
|
||
|
;;////////////////////////////////////////////////////////////////////////////////////////////////;;
|
||
|
;;================================================================================================;;
|
||
|
|
||
|
;;================================================================================================;;
|
||
|
;;////////////////////////////////////////////////////////////////////////////////////////////////;;
|
||
|
;;================================================================================================;;
|
||
|
;! Below is private data you should never use directly from your code ;;
|
||
|
;;================================================================================================;;
|
||
|
;;////////////////////////////////////////////////////////////////////////////////////////////////;;
|
||
|
;;================================================================================================;;
|
||
|
z80._._16color_palette:
|
||
|
dd 0 ; black
|
||
|
dd 0x000000b0 ; blue
|
||
|
dd 0x00b00000 ; red
|
||
|
dd 0x00b000b0 ; magenta
|
||
|
dd 0x0000b000 ; green
|
||
|
dd 0x0000b0b0 ; cyan
|
||
|
dd 0x00b0b000 ; yellow
|
||
|
dd 0x00b0b0b0 ; gray
|
||
|
dd 0 ; black
|
||
|
dd 0x000000ff ; light blue
|
||
|
dd 0x00ff0000 ; light red
|
||
|
dd 0x00ff00ff ; light magenta
|
||
|
dd 0x0000ff00 ; light green
|
||
|
dd 0x0000ffff ; light cyan
|
||
|
dd 0x00ffff00 ; light yellow
|
||
|
dd 0x00ffffff ; white
|