; GnarlPlot screen assembler code V1.01 28/8/04
; Copyright 2008 Jeffrey Lee
; This file is part of GnarlPlot.
; GnarlPlot is free software: you can redistribute it and/or modify
; it under the terms of the GNU General Public License as published by
; the Free Software Foundation, either version 3 of the License, or
; (at your option) any later version.
; GnarlPlot 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 General Public License for more details.
; You should have received a copy of the GNU General Public License
; along with GnarlPlot.  If not, see <http://www.gnu.org/licenses/>.

	GET gp.s

	AREA	scrplot, CODE, READONLY

	EXPORT	gp_screen_hline0
	EXPORT	gp_screen_hline1
	EXPORT	gp_screen_hline2
	EXPORT	gp_screen_hline3

horz_vsmall ; For short lines which don't touch word boundaries
	ADD R2,R2,R3 ; Get back to the original length
	CMP R2,#2
	MOV R12,R12,LSL #3 ; Convert number of bytes into number of bits
	MOV R0,R0,ROR R12 ; Rotate colour by that number
	STRNEB R0,[R1],#1 ; Either 1 or 3
	MOVNE R0,R0,LSR #8 ; Dithering
	STRGEB R0,[R1],#1 ; Either 2 or 3
	MOVGE R0,R0,LSR #8
	STRGEB R0,[R1] ; Either 2 or 3
	MOV PC,R14

gp_screen_hline2 ; R0 = colour word
	  ; R1 -> screen
	  ; R2 = length in pixels
	MOV R2,R2,LSL #2 ; Quadrouple length in pixels to convert from 24bpp to 8bpp
	CMP R2,#0
	MOVLE PC,R14
	B horz_doneend ; Skip start & end pixel code, since there shouldn't be any

gp_screen_hline1 ; R0 = colour word
	  ; R1 -> screen
	  ; R2 = length in pixels
	MOV R2,R2,LSL #1 ; Double length in pixels to convert from 16bpp to 8bpp

	; ** fall through ... **

gp_screen_hline0 ; R0 = colour word
	  ; R1 -> screen
	  ; R2 = length in pixels
	; Draw first & last pixels then branch into general code
	; Need to handle dithering properly since this call could be from screen_hline1 or screen_hline2
	CMP R2,#0
	MOVLE PC,R14
	ANDS R12,R1,#3 ; Any start pix? (0=0, 1=3, 2=2, 3=1)
	BEQ horz_donestart ; No
	RSB R3,R12,#4 ; Invert number to draw
	SUBS R2,R2,R3
	BLE horz_vsmall ; very short line
	MOV R12,R12,LSL #3 ; Convert number of bytes into number of bits
	MOV R12,R0,ROR R12 ; Rotate colour by that number
	CMP R3,#2
	STRNEB R12,[R1],#1 ; Either 1 or 3
	MOVNE R12,R12,LSR #8
	STRGEB R12,[R1],#1 ; Either 2 or 3
	MOVGE R12,R12,LSR #8
	STRGEB R12,[R1],#1 ; Either 2 or 3
horz_donestart
	ANDS R3,R2,#3 ; Get number of end blocks
	BEQ horz_doneend
	BIC R2,R2,#3
	ADD R12,R1,R2 ; Add length to get end pos
	CMP R3,#2
	MOV R3,R0
	STRNEB R3,[R12],#1 ; Either 1 or 3
	MOVNE R3,R3,LSR #8
	STRGEB R3,[R12],#1 ; Either 2 or 3
	MOVGE R3,R3,LSR #8
	STRGEB R3,[R12] ; Either 2 or 3
horz_doneend
	; Now do general word fill routine
	MOVS R2,R2,LSR #3 ; 4 bytes?
	STRCS R0,[R1],#4
	MOV R3,R0 ; Duplicate the word into R3, so the hline3 stuff will work 
gp_screen_hline3 ; R0 = colour word
	  ; R1 -> screen
	  ; R2 = length in pixels
	  ; R3 = colour word 2
	MOVS R2,R2,LSR #1 ; 8 bytes?
	STMCSIA R1!,{R0,R3}
	; Check for end
	MOVEQ PC,R14
	; Otherwise assume fairly long line
	; ... so save regs and fill R4-9 with colour
	STMFD R13!,{R4-R11,R14}
	MOV R4,R0
	MOV R5,R3
	MOVS R2,R2,LSR #1 ; 16?
	STMCSIA R1!,{R0,R3-R5}
	MOV R6,R0
	MOV R7,R3
	MOV R8,R0
	MOV R9,R3
	MOVS R2,R2,LSR #1 ; 32?
	STMCSIA R1!,{R0,R3-R9}
	MOVS R2,R2,LSR #1 ; 64?
	STMCSIA R1!,{R0,R3-R9}
	STMCSIA R1!,{R0,R3-R9}
	LDMEQFD R13!,{R4-R11,PC}
	; Otherwise really long line so fill R10-R12,R14 with colour
	MOV R10,R0
	MOV R11,R3
	MOV R12,R0
	MOV R14,R3
	MOVS R2,R2,LSR #1 ; 128?
	STMCSIA R1!,{R0,R3-R12,R14} ; 48
	STMCSIA R1!,{R0,R3-R12,R14} ; 96
	STMCSIA R1!,{R0,R3-R9} ; 128
	LDMEQFD R13!,{R4-R11,PC}
horz_loop ; Do 256 blocks in a loop
	SUBS R2,R2,#1 ; 256?
	STMGEIA R1!,{R0,R3-R12,R14} ; 48
	STMGEIA R1!,{R0,R3-R12,R14} ; 96
	STMGEIA R1!,{R0,R3-R12,R14} ; 144
	STMGEIA R1!,{R0,R3-R12,R14} ; 192
	STMGEIA R1!,{R0,R3-R12,R14} ; 240
	STMGEIA R1!,{R0,R3-R5} ; 256
	BGT horz_loop
	LDMFD R13!,{R4-R11,PC}

	END

