antoine-source/appleworksgs/Pict/Src/pixels.aii
2023-03-04 03:45:20 +01:00

1 line
16 KiB
Plaintext
Executable File

****************************************************************
* ;
* Pixelmap flipping and rotation routines ;
*______________________________________________________________*
* ;
* Pixelmaps are flipped and rotated with 4-bit Q_Pixels. ;
* (For once, I'm glad that there ISN'T a 640x400 one bit- ;
* per-pixel mode!!) 640 pixel maps that are an odd number ;
* of (640) Q_Pixels wide will lose a column when rotated. ;
* TANSTAAFL. Shit happens. ;
* ;
* It's rather strange, but the SCB for a pixelmap in a ;
* picture is ALWAYS the same as the picture's SCB. This is ;
* incredibly fortuitous, since we only have to worry about ;
* one mode at a time now. ;
* ;
* (At least, I've never SEEN them different....) ;
* ;
****************************************************************
LOAD 'Macros.dump'
INCLUDE 'Pict.equ'
INCLUDE 'Driver.equ'
IMPORT D_BeachBall
IMPORT Q_ChangePictSize
IMPORT Q_Copy2
IMPORT Q_Copy4
IMPORT Q_FixRect
IMPORT Q_JustRect
IMPORT Q_JustRgn
IMPORT Q_manglePt
IMPORT Q_Nop
IMPORT Q_PixelTable
IMPORT Q_addbytes
IMPORT Q_center
IMPORT Q_dstpixsize
IMPORT newptr
IMPORT oldptr
IMPORT Q_picterr
IMPORT Q_pixSCB
IMPORT Q_pixbounds
IMPORT Q_srcpixsize
IMPORT thepoint
IMPORT what
****************************************************************
*
* Q_PixOps -- handle picture opcodes Q_PixRect and Q_PixRgn
*
****************************************************************
Q_PixOps PROC EXPORT
;Using Q_PictData
EXPORT Q_PixRgn
EXPORT Q_PixRect
Q_Mask DS.B 2 ; is there a Q_Mask Q_Region?
toppt DS.B 4 ; upper left of old bounds
*--------------------------------------------------------------*
* Copy a pixelmap opcode and mangle its data ;
*--------------------------------------------------------------*
Q_PixRgn ;
inc Q_Mask
bra dopixels
Q_PixRect ;
stz Q_Mask
dopixels jsl Q_Nop ; copy opcode
lda [<oldptr]
and #$80 ; D_Save mode
sta Q_pixSCB
jsl Q_Copy4 ; copy SCB and BWvsColor
spacelong ; get the size of the old pixelmap
pushword [<oldptr] ; old width
subword [<oldptr]:#6,[<oldptr]:#2,s ; old height
_Multiply
pulllong Q_srcpixsize
movelong [<oldptr]:#2,toppt ; get upper left Q_Point of bounds
cmpw <what,#Q_rotr ; am I rotating?
jlt pixflip ; must not be
*--------------------------------------------------------------*
* ROTATE ;
*--------------------------------------------------------------*
subword [<oldptr]:#6,toppt,a ; get height of bounds
dec a ; convert Q_Pixels->bytes
lsr a
inc a
sta [<newptr] ; this is the width of the rotated map
movelong #0,[<newptr]:#2 ; adjust first pt. to 0
subword [<oldptr]:#6,toppt,<thepoint ; get the bounds
subword [<oldptr]:#8,toppt+2,<thepoint+2 ; and adjust
ldx <thepoint ; flip the Q_Point diagonally
lda <thepoint+2
sta <thepoint
stx <thepoint+2
movelong <thepoint,Q_pixbounds ; remember the D_New bounds NOW
lda Q_pixSCB ; adjust for 640 mode?
beq newboundsok
lsr <thepoint ; if so, halve the old width
asl <thepoint+2 ; and double the D_New width
newboundsok movelong <thepoint,[<newptr]:#6 ; store D_New (adjusted) bounds
spacelong ; compute the size of the dest. map
pushword [<newptr] ; D_New width
pushword [<newptr]:#6 ; D_New height
_Multiply
pulllong Q_dstpixsize
addwl #10,<oldptr ; adjust the pointers
addwl #10,<newptr
sublong Q_dstpixsize,Q_srcpixsize,Q_addbytes
jsl Q_ChangePictSize
jcc rotsrcrect
sta Q_picterr
brl bye
rotsrcrect pushlong Q_center ; Flip around the pixelmap's
movelong Q_pixbounds,Q_center ; Q_center, not the picture's
noshift subword [<oldptr],toppt,<thepoint+2 ; adjust upper left pt
subword [<oldptr]:#2,toppt+2,<thepoint ; and flip diagonally
getsrc1 lda <what ; Now r-rotation becomes HACK
dec a ; h-flipping, and l-rotation
dec a ; becomes v-flipping
jtl Q_manglePt ; KCAH
lda Q_pixSCB ; adjust for 640 mode?
beq srcok1
lsr <thepoint
asl <thepoint+2
srcok1 movelong <thepoint,[<newptr]
subword [<oldptr]:#4,toppt,<thepoint+2 ; repeat for
subword [<oldptr]:#6,toppt+2,<thepoint ; lower right pt
getsrc2 lda <what ; Now r-rotation becomes HACK
dec a ; h-flipping, and l-rotation
dec a ; becomes v-flipping
jtl Q_manglePt ; KCAH
lda Q_pixSCB ; adjust for 640 mode?
beq srcok2
lsr <thepoint
asl <thepoint+2
srcok2 movelong <thepoint,[<newptr]:#4
pulllong Q_center ; back to the picture's Q_center
addwl #8,<oldptr
jsl Q_FixRect ; legalize the D_New source rectangle
brl gotsrcrect
*--------------------------------------------------------------*
* FLIP ;
*--------------------------------------------------------------*
pixflip jsl Q_Copy2 ; copy width
subword [<oldptr]:#4,toppt,Q_pixbounds ; get 'Q_center'
subword [<oldptr]:#6,toppt+2,Q_pixbounds+2 ; of bounds
movelong #0,[<newptr] ; adjust the D_New bounds
movelong Q_pixbounds,[<newptr]:#4 ; Q_Rect to (0,0)
addwl #8,<oldptr ; adjust the pointers (duh...)
addwl #8,<newptr
movelong Q_srcpixsize,Q_dstpixsize ; the D_New map is the same size!
pushlong Q_center ; flip the source Q_Rect around
movelong Q_pixbounds,Q_center ; the Q_center of the bounds Q_Rect
subword [<oldptr],toppt,<thepoint ; adjust src Q_Rect
subword [<oldptr]:#2,toppt+2,<thepoint+2 ; to match bounds
jtl Q_manglePt,<what
movelong <thepoint,[<newptr]
subword [<oldptr]:#4,toppt,<thepoint
subword [<oldptr]:#6,toppt+2,<thepoint+2
jtl Q_manglePt,<what
movelong <thepoint,[<newptr]:#4
jsl Q_FixRect
addwl #8,<oldptr
pulllong Q_center ; back to the picture's coordinates
gotsrcrect jsl Q_JustRect ; copy/mangle the dstrect
jsl Q_Copy2 ; copy the transfer mode
lda Q_Mask ; is there a Q_Mask Q_Region?
jeq noregion
jsl Q_JustRgn ; if so, mangle it!
noregion pushlong <oldptr ; now for the real work....
pushlong <newptr
jtl Q_PixelTable,<what ; (no errors possible)
addlong <oldptr,Q_srcpixsize,<oldptr
addlong <newptr,Q_dstpixsize,<newptr
clc
bye rtl
ENDP
****************************************************************
*
* Q_FlipHMap(srcpix:l,dstpix:l) -- flip a pixelmap horizontally
*_______________________________________________________________
*
* NOTE: The destination bitmap is assumed to be allocated.
* Q_pixbounds should contain the coordinates of the lower
* right corner of the destination map, and Q_pixSCB should
* contain the pixel map's SCB byte. Row sizes and total
* sizes (bytes) are derived from this Q_Point. No error
* checking is performed -- Q_FlipHMap and its siblings
* simply D_Write over whatever memory you Q_Point them at.
*
****************************************************************
Q_FlipHMap PROC EXPORT
;Using Q_PictData
input srcpix:l,dstpix:l
local rowsize:w,slop:w,rcount:w,mode:w
local soffset:w,doffset:w,pixel:w,temp:w
begin
spaceword
_GetMasterSCB
pla
and #$80
sta mode
lda Q_pixbounds+2 ; get rowsize in bytes
dec a
lsr a
ldx Q_pixSCB ; 640 mode?
beq gotwid
lsr a
gotwid inc a
sta rowsize
lda Q_pixbounds+2 ; is there an extra pixel on the edge?
ldx Q_pixSCB ; am i 640 mode?
beq getslop
dec a ; if so, then are there two or three
lsr a ; extra Q_Pixels on the edge?
inc a
getslop and #1
sta slop ; (slop = number of ununsed low nybbles)
stz rcount ; start at row zero
*--------------------------------------------------------------*
* ROW LOOP ;
*--------------------------------------------------------------*
rloop
jsl D_BeachBall
stz soffset ; start at the left end of source...
moveword rowsize,doffset ; ...and the right end of dest.
lda slop ; sloppy?
jne slopstart
*--------------------------------------------------------------*
* Neat point loop: the maps are an even number of Q_Pixels wide ;
*--------------------------------------------------------------*
neatloop moveword [srcpix]:soffset,a ; get the byte
and #$ff ; a = 0 0 X Y reverse the nybbles
asl a
asl a
asl a
asl a ; a = 0 X Y 0
sta pixel
xba ; a = Y 0 0 B
ora pixel ; a = Y X Y X
; ldx mode
; beq neat320
; jsr FlipNyps
neat320 dec doffset ; adjust the offset
movebyte a,[dstpix]:doffset ; put the byte
lda doffset ; done?
jeq rdone
inc soffset ; adjust the offset
brl neatloop
*--------------------------------------------------------------*
* Sloppy Q_Point loop: the maps are an odd number of Q_Pixels wide ;
*--------------------------------------------------------------*
slopstart stz pixel ; initialize this.
sloploop moveword [srcpix]:soffset,a ; get the byte
pha ; D_Save it
and #$f0 ; get the high nybble
ora pixel ; fill up the byte
; ldx mode
; beq slop320
; jsr FlipNyps
slop320 dec doffset
movebyte a,[dstpix]:doffset ; D_Write it out
lda doffset ; fix the offset
jeq endslop ; am I done yet?
pla ; restore the byte from above
and #$f ; get the low nybble
sta pixel ; initialize the byte
inc soffset ; fix the offset
brl sloploop ; repeat
endslop plx ; clear up the stack
*--------------------------------------------------------------*
rdone addwl rowsize,srcpix ; We're done with one row.
addwl rowsize,dstpix ; D_Update the pointers.
inc rcount ; have I reached the last row?
cmpw rcount,Q_pixbounds
jlt rloop ; nope. try again.
return ; If so, I'm done!!
; ;--------------------------------------------------------------*
; ; FlipNyps -- reverse the nyp order in each nyble in a ;
; ; (For those who don't know, a 'nyp' is Q_half a nybble.) ;
; ;--------------------------------------------------------------*
; FlipNyps tax
; and #$3333 ; get the low nyps
; asl a
; asl a ; move them up
; sta temp
; txa
; and #$cccc ; get the high nyps
; lsr a
; lsr a ; move them down
; ora temp
; rts
;
ENDP
****************************************************************
*
* Q_FlipVMap(srcpix:l,dstpix:l) -- flip a pixelmap vertically
*
****************************************************************
Q_FlipVMap PROC EXPORT
;Using Q_PictData
input srcpix:l,dstpix:l
local rowsize:w,rcount:w
begin
lda Q_pixbounds+2 ; get rowsize in bytes
dec a
lsr a
ldx Q_pixSCB ; 640 mode?
beq gotwid
lsr a
gotwid inc a
sta rowsize
stz rcount ; start at (source) row zero
spacelong
subword Q_pixbounds,#1,s
pushword rowsize
_Multiply
addlong s,dstpix,dstpix ; start at the last destination row
rloop
jsl D_BeachBall
pushlong srcpix ; copy a row
pushlong dstpix
pushword #0 ; amount high word
pushword rowsize ; amount low word
_BlockMove
addwl rowsize,srcpix ; D_Update the pointers
subwl rowsize,dstpix
inc rcount
cmpw rcount,Q_pixbounds ; done?
jlt rloop
return
ENDP
****************************************************************
*
* Q_RotRMap(srcpix:l,dstpix:l) -- rotate a pixelmap clockwise
*
* Source is scanned rightwards a column at a time, starting
* at the top of each column. Destination is scanned
* downward a row at a time, starting at the right end
* of each row.
*
****************************************************************
Q_RotRMap PROC EXPORT
;Using Q_PictData
input srcpix:l,dstpix:l
local srowsize:w,drowsize:w
local soffset:w,doffset:w,rcount:w,srcrow:l
local pixel:w,slop:w,dside:w,sside:w
begin
lda Q_pixSCB
beq boundsok
dec Q_pixbounds ; adjust OLD width of bounds ONLY
lsr Q_pixbounds
inc Q_pixbounds ; <for use by Q_RotRMap and Q_RotLMap>
boundsok lda Q_pixbounds ; get source rowsize in bytes
dec a
lsr a ; (already adjusted for mode)
inc a
sta srowsize
lda Q_pixbounds+2 ; get destination rowsize in bytes
dec a
lsr a ; (already adjusted for mode)
inc a
sta drowsize
lda Q_pixbounds+2 ; is there an extra pixel on the edge
and #1 ; of the destination map?
sta slop
moveword Q_pixbounds,rcount
moveword #1,sside
stz soffset ; (start at the left of source)
rloop
jsl D_BeachBall
moveword drowsize,doffset ; initialize the offsets
movelong srcpix,srcrow ; (start at the top of source)
moveword slop,dside ; and other goodies
stz pixel
ploop moveword [srcrow]:soffset,a ; get the source byte
ldx sside ; which side is the pixel on?
bne shipixel
and #$f ; it's low.
ldx dside ; should it be?
beq putpixel
asl a
asl a
asl a
asl a
bra gotpixel
shipixel and #$f0 ; it's high
ldx dside ; should it be?
bne gotpixel
lsr a
lsr a
lsr a
lsr a
gotpixel ora pixel
putpixel sta pixel
lda dside ; am I done with this byte?
beq nowrite
dec doffset ; move backwards through the dest. row
movebyte pixel,[dstpix]:doffset
lda doffset ; am I done with this row?
jeq rdone
stz dside
stz pixel
bra nextp
nowrite inc dside
nextp addwl srowsize,srcrow ; next source row.
brl ploop
rdone dec rcount
jeq bye
addwl drowsize,dstpix ; next destination row
lda sside
eor #1
sta sside
beq stayput ; if sside = 0, same src byte column
addwl #1,soffset ; else, use next one
stayput brl rloop
bye return
ENDP
****************************************************************
*
* Q_RotLMap(srcpix:l,dstpix:l) -- rotate a pixelmap anticlockwise
*
* Source is scanned leftwards a column at a time, starting
* at the bottom of each column. Destination is scanned
* downward a row at a time, starting at the right end
* of each row.
*
****************************************************************
Q_RotLMap PROC EXPORT
;Using Q_PictData
input srcpix:l,dstpix:l
local srowsize:w,drowsize:w,spicsize:l
local soffset:w,doffset:w,rcount:w,srcrow:l
local pixel:w,slop:w,dside:w,sside:w
begin
lda Q_pixSCB
beq boundsok
dec Q_pixbounds ; adjust OLD width of bounds ONLY
lsr Q_pixbounds
inc Q_pixbounds ; <for use by Q_RotRMap and Q_RotLMap>
boundsok lda Q_pixbounds ; get source rowsize in bytes
dec a
lsr a ; (already adjusted for mode)
inc a
sta srowsize
lda Q_pixbounds+2 ; get destination rowsize in bytes
dec a
lsr a ; (already adjusted for mode)
inc a
sta drowsize
lda Q_pixbounds+2 ; is there an extra pixel on the edge
and #1 ; of the destination map?
sta slop
moveword Q_pixbounds,rcount
lda Q_pixbounds ; how about the source map?
and #1
sta sside
spacelong ; how big is the whole thing?
pushword srowsize
subword Q_pixbounds+2,#1,s
_Multiply
pulllong spicsize
moveword srowsize,soffset ; start at right of source map
dec soffset
rloop
jsl D_BeachBall
moveword drowsize,doffset ; initialize the offsets
addlong srcpix,spicsize,srcrow ; (start at bottom of source)
; subwl srowsize,srcrow
moveword slop,dside ; and other goodies
stz pixel
ploop moveword [srcrow]:soffset,a ; get the source byte
ldx sside ; which side is the pixel on?
bne shipixel
and #$f ; it's low.
ldx dside ; should it be?
beq gotpixel
asl a
asl a
asl a
asl a
bra gotpixel
shipixel and #$f0 ; it's high
ldx dside ; should it be?
bne gotpixel
lsr a
lsr a
lsr a
lsr a
gotpixel ora pixel
putpixel sta pixel
lda dside ; am I done with this byte?
beq nowrite
dec doffset ; move backwards through the dest. row
movebyte pixel,[dstpix]:doffset
lda doffset ; am I done with this row?
jeq rdone
stz dside
stz pixel
bra nextp
nowrite inc dside
nextp subwl srowsize,srcrow ; previous source row.
brl ploop
rdone dec rcount
jeq bye
addwl drowsize,dstpix ; next destination row
lda sside
eor #1
sta sside
bne stayput ; if sside = 1, same src byte column
dec soffset ; else, use previous one
stayput brl rloop
bye return
ENDP
END