ld bc,(hl)

The place for codemasters or beginners to talk about programming any language for the Spectrum.
Post Reply
User avatar
777
Manic Miner
Posts: 512
Joined: Fri Jun 26, 2020 11:23 am
Location: sw uk

Re: ld bc,(hl)

Post by 777 »

thank you all, its getting better. i did think that there was another problem with this code and not just that ld instruction problem. it there a way of positioning the box without altering all the data frames? if i can move it into the middle of the screen, this may stop the glitches, as from experience this routine doesnt like too be to far across the screen in the x position
i started programming the spectrum when i was 8 :-

1 plot rnd*255,rnd*175
2 goto 1
User avatar
777
Manic Miner
Posts: 512
Joined: Fri Jun 26, 2020 11:23 am
Location: sw uk

Re: ld bc,(hl)

Post by 777 »

i managed to get it to work while trying something else. i wanted to move it in the x position. it stays in the same place but gets rid of the glitches. odd. still dont know how to move it to another part of the screen, though. i also tried it with sub but sbc seem less flickery. heres what i added

Code: Select all

ld a,100
sbc a,c	

Code: Select all

	org 50000
Endless_Loop:
		ld hl,Edge_Data
		ld b,18
Frame_Loop:
		push bc				; preserve B for loop
	
		ld b,12
		push hl
Edge_Loop:
		push bc				; preserve B for loop
		ld c,(hl)
ld a,100
sbc a,c			; B = ypos1 C = xpos1
		inc hl
		ld b,(hl)
		inc hl
		ld e,(hl)	
ld a,100
sbc a,e		; D = ypos2 E = xpos2
		inc hl
		ld d,(hl)	
		inc hl
		push hl				; preserve edge pointer
		call Draw_Line
		pop hl
  		pop bc
		djnz Edge_Loop
		
		ld bc,$40ff			; Steve Wetherill floating bus frame sync from Sidewize
		ld e,%00111010			; red ink on white paper
sync:	
		;ld a,r				; padding instruction
		;in a,(c)
		;cp e
		;jp nz,sync
		
		halt

		
		ld b,12
		pop hl
Erase_Loop:
		push bc				; preserve B for loop
		ld c,(hl)

ld a,100
sbc a,c			; B = ypos1 C = xpos1
		inc hl
		ld b,(hl)
		inc hl
		ld e,(hl)	

ld a,100
sbc a,e		; D = ypos2 E = xpos2
		inc hl
		ld d,(hl)
		inc hl
		push hl				; preserve edge pointer
		call Erase_Line
		pop hl
  		pop bc
		djnz Erase_Loop

		
		pop bc
		djnz Frame_Loop
		jp Endless_Loop
		ret	




; Plot routine
; B = Y pixel position
; C = X pixel position
;
Plot:                   CALL Get_Pixel_Address          ; Get screen address in HL, pixel position (0 to 7) in A
                        LD BC,Plot_Point                ; Address of point lookup table
                        ADD A,C                         ; Add pixel position to get entry in table
                        LD C,A
                        LD A,(BC)                       ; Get pixel data from table
                        OR (HL)                         ; OR with screen data
                        LD (HL),A                       ; Write back to screen
                        RET
 
 
; Unplot routine
; B = Y pixel position
; C = X pixel position
;
Unplot:                 CALL Get_Pixel_Address          ; Same as Plot...
                        LD BC,Unplot_Point
                        ADD A,C
                        LD C,A
                        LD A,(BC)
                        AND (HL)                        ; AND with screen data
                        LD (HL),A
                        RET


; Draw Line routine
; B = Y pixel position 1
; C = X pixel position 1
; D = Y pixel position 2
; E = X pixel position 2
;
Draw_Line:              LD A,D                          ; Check whether we are going to be drawing up
                        CP B
                        JR NC,Draw_Line_1
 
                        PUSH BC                         ; If we are, then this neat trick swaps BC and DE
                        PUSH DE                         ; using the stack, forcing the line to be always
                        POP BC                          ; drawn downwards
                        POP DE
 
Draw_Line_1:            CALL Get_Pixel_Address          ; Get screen address in HL, pixel position (0-7) in A
;
; At this point we have
;  A = Pixel position (0-7)
; HL = Screen address of the start point
; BC = Start coordinate (B=Y1, C=X1)
; DE = End coordinates  (D=Y2, E=X2)
;
                        LD IX,Plot_Point                ; Point to the Plot_Point table
                        ADD A,IXL                       ; Add the pixel position to get entry in table
                        LD IXL,A
 
                        LD A,D                          ; Calculate the line height in B (Y2-Y1)
                        SUB B
                        LD B,A
         
                        LD A,E                          ; Calculate the line width in C (X2-X1)
                        SUB C
                        JR C,Draw_Line_X1               ; If carry set (negative result) then we are drawing from right to left
;
; This bit of code mods the main loop for drawing left to right
;
                        LD C,A                          ; Store the line width
                        LD A,0x2C                       ; Code for INC L
                        LD (Draw_Line_Q1_M3),A          ; Mod the code
                        LD (Draw_Line_Q2_M3),A
                        LD A,0x0A                       ; Code for RRC D (CB 0A)
                        JR Draw_Line_X2                 ; Skip the next bit
;
; This bit of code mods the main loop for drawing right to left
;
Draw_Line_X1:           NEG                             ; The width of line is negative, so make it positive again
                        LD C,A                          ; Store the line width
                        LD A,0x2D                       ; Code for DEC L
                        LD (Draw_Line_Q1_M3),A
                        LD (Draw_Line_Q2_M3),A
                        LD A,0x02                       ; Code for RLC D (CB 02)
;
; We've got the basic information at this point
;
Draw_Line_X2:           LD (Draw_Line_Q1_M2 + 1),A      ; A contains the code for RLC D or RRC D, so make the mods
                        LD (Draw_Line_Q2_M2 + 1),A
                        LD D,(IX+0)                     ; Get the pixel data from the Point_Plot table
                        LD A,B                          ; Check if B and C are 0
                        OR C
                        JR NZ,Draw_Line_Q               ; There is a line to draw, so skip to the next bit
                        LD A,(HL)                       ; Here we've got a single point line, so plot and return
                        OR D
                        LD (HL),A
                        RET
;
; At this point
; HL = Screen address of the start point
;  B = Line height
;  C = Line width
;  D = Pixel data
;
Draw_Line_Q:            LD A,B                          ; Work out which diagonal we are on
                        CP C
                        JR NC,Draw_Line_Q2
;
; This bit of code draws the line where B<C (more horizontal than vertical)
;
Draw_Line_Q1:           LD A,C
                        LD (Draw_Line_Q1_M1 + 1),A      ; Self-mod the code again to store the line width
                        LD C,B
                        LD B,A
                        LD E,C                          ; Calculate the error value
                        SRL E
Draw_Line_Q1_L:         LD A,(HL)                       ; Plot the pixel
                        OR D
                        LD (HL),A
                        LD A,E
                        SUB C
                        LD E,A
                        JR NC,Draw_Line_Q1_M2
Draw_Line_Q1_M1:        ADD A,0                         ; Add the line height (previously stored; self modifying code)
                        LD E,A
                        CALL Pixel_Address_Down
Draw_Line_Q1_M2:        RRC D                           ; Rotate the pixel right or left; more self-modifying code
                        JR NC,Draw_Line_Q1_S
Draw_Line_Q1_M3:        INC L                           ; If we get a carry then move to adjacent screen address; more self modifying code
Draw_Line_Q1_S:         DJNZ Draw_Line_Q1_L             ; Loop until the line is drawn
                        RET
;
; This bit draws the line where B>=C (more vertical than horizontal, or diagonal)
;
Draw_Line_Q2:           LD (Draw_Line_Q2_M1 + 1),A
                        LD E,C                          ; Calculate the error value
                        SRL E
Draw_Line_Q2_L:         LD A,(HL)                       ; Plot the pixel
                        OR D
                        LD (HL),A
                        LD A,E                          ; Get the error value
                        SUB C                           ; Add the line length to it (X2-X1)
                        JR NC,Draw_Line_Q2_S            ; Skip the next bit if we don't get a carry
Draw_Line_Q2_M1:        ADD A,0                         ; Add the line height (previously stored; self modifying code)
Draw_Line_Q2_M2:        RRC D                           ; Rotates the pixel right with carry
                        JR NC,Draw_Line_Q2_S
Draw_Line_Q2_M3:        INC L                           ; If we get a carry then move to adjacent screen address; more self modifying code
Draw_Line_Q2_S:         LD E,A                          ; Store the error value back in
                        CALL Pixel_Address_Down         ; And also move down
                        DJNZ Draw_Line_Q2_L
                        RET
 
; Erase Line routine
; B = Y pixel position 1
; C = X pixel position 1
; D = Y pixel position 2
; E = X pixel position 2
;
Erase_Line:             LD A,D                          ; Check whether we are going to be drawing up
                        CP B
                        JR NC,Erase_Line_1
 
                        PUSH BC                         ; If we are, then this neat trick swaps BC and DE
                        PUSH DE                         ; using the stack, forcing the line to be always
                        POP BC                          ; drawn downwards
                        POP DE
 
Erase_Line_1:           CALL Get_Pixel_Address          ; Get screen address in HL, pixel position (0-7) in A
;
; At this point we have
;  A = Pixel position (0-7)
; HL = Screen address of the start point
; BC = Start coordinate (B=Y1, C=X1)
; DE = End coordinates  (D=Y2, E=X2)
;
                        LD IX,Unplot_Point              ; Point to the Unplot_Point table
                        ADD A,IXL                       ; Add the pixel position to get entry in table
                        LD IXL,A
 
                        LD A,D                          ; Calculate the line height in B (Y2-Y1)
                        SUB B
                        LD B,A
         
                        LD A,E                          ; Calculate the line width in C (X2-X1)
                        SUB C
                        JR C,Erase_Line_X1              ; If carry set (negative result) then we are drawing from right to left
;
; This bit of code mods the main loop for drawing left to right
;
                        LD C,A                          ; Store the line width
                        LD A,0x2C                       ; Code for INC L
                        LD (Erase_Line_Q1_M3),A         ; Mod the code
                        LD (Erase_Line_Q2_M3),A
                        LD A,0x0A                       ; Code for RRC D (CB 0A)
                        JR Erase_Line_X2                ; Skip the next bit
;
; This bit of code mods the main loop for drawing right to left
;
Erase_Line_X1:          NEG                             ; The width of line is negative, so make it positive again
                        LD C,A                          ; Store the line width
                        LD A,0x2D                       ; Code for DEC L
                        LD (Erase_Line_Q1_M3),A
                        LD (Erase_Line_Q2_M3),A
                        LD A,0x02                       ; Code for RLC D (CB 02)
;
; We've got the basic information at this point
;
Erase_Line_X2:          LD (Erase_Line_Q1_M2 + 1),A     ; A contains the code for RLC D or RRC D, so make the mods
                        LD (Erase_Line_Q2_M2 + 1),A
                        LD D,(IX+0)                     ; Get the pixel data from the Unplot_Point table
                        LD A,B                          ; Check if B and C are 0
                        OR C
                        JR NZ,Erase_Line_Q              ; There is a line to draw, so skip to the next bit
                        LD A,(HL)                       ; Here we've got a single point line, so plot and return
                        AND D
                        LD (HL),A
                        RET
;
; At this point
; HL = Screen address of the start point
;  B = Line height
;  C = Line width
;  D = Pixel data
;
Erase_Line_Q:           LD A,B                          ; Work out which diagonal we are on
                        CP C
                        JR NC,Erase_Line_Q2
;
; This bit of code draws the line where B<C (more horizontal than vertical)
;
Erase_Line_Q1:          LD A,C
                        LD (Erase_Line_Q1_M1 + 1),A     ; Self-mod the code again to store the line width
                        LD C,B
                        LD B,A
                        LD E,C                          ; Calculate the error value
                        SRL E
Erase_Line_Q1_L:        LD A,(HL)                       ; Unplot the pixel
                        AND D
                        LD (HL),A
                        LD A,E
                        SUB C
                        LD E,A
                        JR NC,Erase_Line_Q1_M2
Erase_Line_Q1_M1:       ADD A,0                         ; Add the line height (previously stored; self modifying code)
                        LD E,A
                        CALL Pixel_Address_Down
Erase_Line_Q1_M2:       RRC D                           ; Rotate the pixel right or left; more self-modifying code
                        JR C,Erase_Line_Q1_S            ; Note the change here from the Draw_Line routine
Erase_Line_Q1_M3:       INC L                           ; If we get no carry then move to adjacent screen address; more self modifying code
Erase_Line_Q1_S:        DJNZ Erase_Line_Q1_L            ; Loop until the line is drawn
                        RET
;
; This bit draws the line where B>=C (more vertical than horizontal, or diagonal)
;
Erase_Line_Q2:          LD (Erase_Line_Q2_M1 + 1),A
                        LD E,C                          ; Calculate the error value
                        SRL E
Erase_Line_Q2_L:        LD A,(HL)                       ; Unplot the pixel
                        AND D
                        LD (HL),A
                        LD A,E                          ; Get the error value
                        SUB C                           ; Add the line length to it (X2-X1)
                        JR NC,Erase_Line_Q2_S           ; Skip the next bit if we don't get a carry
Erase_Line_Q2_M1:       ADD A,0                         ; Add the line height (previously stored; self modifying code)
Erase_Line_Q2_M2:       RRC D                           ; Rotates the pixel right with carry
                        JR C,Erase_Line_Q2_S            ; Note the change here from the Draw_Line routine
Erase_Line_Q2_M3:       INC L                           ; If we get no carry then move to adjacent screen address; more self modifying code
Erase_Line_Q2_S:        LD E,A                          ; Store the error value back in
                        CALL Pixel_Address_Down         ; And also move down
                        DJNZ Erase_Line_Q2_L
                        RET

;; GET BUFFER PIXEL ADDRESS
;; B=y-pos C=x-pos 
;; Returns: HL=Adress of pixel A=Byte of the pixel

Get_Buffer_Address:

	ld l,0        ;
	ld h,b        ; B contains the Y-POS
	srl h         ;
	rr l          ;
	srl h         ;
	rr l          ; Shifts right 3x, then OR's low byte with 11100000 
	srl h         ;
	rr l          ; divide by 8?
	ld a,h        ;
	or 224        ; 11100000
	ld h,a        ;

 	ld a,c        ; C contains the X-POS
 	rra           ;
 	rra           ; divide by 8
 	rra           ;
 	and 31        ; 00011111 - strip out rolled in carry bytes
 	or l          ;
 	ld l,a        ;
 	ld a,c        ;
 	and 7         ; 00000111
 	ret           ;


; Get screen address
; B = Y pixel position
; C = X pixel position
; Returns address in HL and pixel position within character in A
;
Get_Pixel_Address:      LD A,B                          ; Calculate Y2,Y1,Y0
                        AND %00000111                   ; Mask out unwanted bits
                        OR %01000000                    ; Set base address of screen
                        LD H,A                          ; Store in H
                        LD A,B                          ; Calculate Y7,Y6
                        RRA                             ; Shift to position
                        RRA
                        RRA
                        AND %00011000                   ; Mask out unwanted bits
                        OR H                            ; OR with Y2,Y1,Y0
                        LD H,A                          ; Store in H
                        LD A,B                          ; Calculate Y5,Y4,Y3
                        RLA                             ; Shift to position
                        RLA
                        AND %11100000                   ; Mask out unwanted bits
                        LD L,A                          ; Store in L
                        LD A,C                          ; Calculate X4,X3,X2,X1,X0
                        RRA                             ; Shift into position
                        RRA
                        RRA
                        AND %00011111                   ; Mask out unwanted bits
                        OR L                            ; OR with Y5,Y4,Y3
                        LD L,A                          ; Store in L
                        LD A,C
                        AND 7
                        RET

; Move HL down one pixel line
;
Pixel_Address_Down:     INC H                           ; Go down onto the next pixel line
                        LD A,H                          ; Check if we have gone onto next character boundary
                        AND 7
                        RET NZ                          ; No, so skip the next bit
                        LD A,L                          ; Go onto the next character line
                        ADD A,32
                        LD L,A
                        RET C                           ; Check if we have gone onto next third of screen
                        LD A,H                          ; Yes, so go onto next third
                        SUB 8
                        LD H,A
                        RET
 
; Note that the functions above only work if each of these tables are in a byte boundary
;
Plot_Point:             DB %10000000,%01000000,%00100000,%00010000,%00001000,%00000100,%00000010,%00000001
Unplot_Point:           DB %01111111,%10111111,%11011111,%11101111,%11110111,%11111011,%11111101,%11111110
 
Plot_Line_LHS:          DB %11111111,%01111111,%00111111,%00011111,%00001111,%00000111,%00000011,%00000001
Plot_Line_RHS:          DB %10000000,%11000000,%11100000,%11110000,%11111000,%11111100,%11111110,%11111111

Edge_Data:

;;;EDGE DATA


;;;FRAME #1 0 degrees
     defb 164,7,231,7
     defb 231,7,231,74
     defb 231,74,164,74
     defb 164,74,164,7
     defb 218,21,178,21
     defb 178,21,178,61
     defb 178,61,218,61
     defb 218,61,218,21
     defb 164,7,178,21
     defb 231,7,218,21
     defb 231,74,218,61
     defb 164,74,178,61

;;;FRAME #2 5 degrees
     defb 162,8,229,6
     defb 229,6,229,75
     defb 229,75,162,73
     defb 162,73,162,8
     defb 220,20,180,21
     defb 180,21,180,60
     defb 180,60,220,61
     defb 220,61,220,20
     defb 162,8,180,21
     defb 229,6,220,20
     defb 229,75,220,61
     defb 162,73,180,60

;;;FRAME #3 10 degrees
     defb 161,9,226,5
     defb 226,5,226,76
     defb 226,76,161,72
     defb 161,72,161,9
     defb 222,20,182,21
     defb 182,21,182,60
     defb 182,60,222,61
     defb 222,61,222,20
     defb 161,9,182,21
     defb 226,5,222,20
     defb 226,76,222,61
     defb 161,72,182,60

;;;FRAME #4 15 degrees
     defb 160,10,223,4
     defb 223,4,223,77
     defb 223,77,160,71
     defb 160,71,160,10
     defb 224,19,184,21
     defb 184,21,184,60
     defb 184,60,224,62
     defb 224,62,224,19
     defb 160,10,184,21
     defb 223,4,224,19
     defb 223,77,224,62
     defb 160,71,184,60

;;;FRAME #5 20 degrees
     defb 160,11,219,4
     defb 219,4,219,77
     defb 219,77,160,70
     defb 160,70,160,11
     defb 225,19,186,22
     defb 186,22,186,59
     defb 186,59,225,62
     defb 225,62,225,19
     defb 160,11,186,22
     defb 219,4,225,19
     defb 219,77,225,62
     defb 160,70,186,59

;;;FRAME #6 25 degrees
     defb 160,12,216,3
     defb 216,3,216,78
     defb 216,78,160,69
     defb 160,69,160,12
     defb 227,18,188,22
     defb 188,22,188,59
     defb 188,59,227,63
     defb 227,63,227,18
     defb 160,12,188,22
     defb 216,3,227,18
     defb 216,78,227,63
     defb 160,69,188,59

;;;FRAME #7 30 degrees
     defb 160,13,211,3
     defb 211,3,211,78
     defb 211,78,160,68
     defb 160,68,160,13
     defb 229,18,191,22
     defb 191,22,191,59
     defb 191,59,229,63
     defb 229,63,229,18
     defb 160,13,191,22
     defb 211,3,229,18
     defb 211,78,229,63
     defb 160,68,191,59

;;;FRAME #8 35 degrees
     defb 160,14,207,2
     defb 207,2,207,79
     defb 207,79,160,67
     defb 160,67,160,14
     defb 230,17,193,22
     defb 193,22,193,59
     defb 193,59,230,64
     defb 230,64,230,17
     defb 160,14,193,22
     defb 207,2,230,17
     defb 207,79,230,64
     defb 160,67,193,59

;;;FRAME #9 40 degrees
     defb 161,15,202,2
     defb 202,2,202,79
     defb 202,79,161,66
     defb 161,66,161,15
     defb 232,16,195,22
     defb 195,22,195,59
     defb 195,59,232,65
     defb 232,65,232,16
     defb 161,15,195,22
     defb 202,2,232,16
     defb 202,79,232,65
     defb 161,66,195,59

;;;FRAME #10 45 degrees
     defb 162,16,198,2
     defb 198,2,198,79
     defb 198,79,162,66
     defb 162,66,162,16
     defb 233,16,198,22
     defb 198,22,198,59
     defb 198,59,233,66
     defb 233,66,233,16
     defb 162,16,198,22
     defb 198,2,233,16
     defb 198,79,233,66
     defb 162,66,198,59

;;;FRAME #11 50 degrees
     defb 163,16,193,2
     defb 193,2,193,79
     defb 193,79,163,65
     defb 163,65,163,16
     defb 234,15,200,22
     defb 200,22,200,59
     defb 200,59,234,66
     defb 234,66,234,15
     defb 163,16,200,22
     defb 193,2,234,15
     defb 193,79,234,66
     defb 163,65,200,59

;;;FRAME #12 55 degrees
     defb 165,17,188,2
     defb 188,2,188,79
     defb 188,79,165,64
     defb 165,64,165,17
     defb 235,14,202,22
     defb 202,22,202,59
     defb 202,59,235,67
     defb 235,67,235,14
     defb 165,17,202,22
     defb 188,2,235,14
     defb 188,79,235,67
     defb 165,64,202,59

;;;FRAME #13 60 degrees
     defb 166,18,184,3
     defb 184,3,184,78
     defb 184,78,166,63
     defb 166,63,166,18
     defb 235,13,204,22
     defb 204,22,204,59
     defb 204,59,235,68
     defb 235,68,235,13
     defb 166,18,204,22
     defb 184,3,235,13
     defb 184,78,235,68
     defb 166,63,204,59

;;;FRAME #14 65 degrees
     defb 168,18,179,3
     defb 179,3,179,78
     defb 179,78,168,63
     defb 168,63,168,18
     defb 235,12,207,22
     defb 207,22,207,59
     defb 207,59,235,69
     defb 235,69,235,12
     defb 168,18,207,22
     defb 179,3,235,12
     defb 179,78,235,69
     defb 168,63,207,59

;;;FRAME #15 70 degrees
     defb 170,19,176,4
     defb 176,4,176,77
     defb 176,77,170,62
     defb 170,62,170,19
     defb 235,11,209,22
     defb 209,22,209,59
     defb 209,59,235,70
     defb 235,70,235,11
     defb 170,19,209,22
     defb 176,4,235,11
     defb 176,77,235,70
     defb 170,62,209,59

;;;FRAME #16 75 degrees
     defb 171,19,172,4
     defb 172,4,172,77
     defb 172,77,171,62
     defb 171,62,171,19
     defb 235,10,211,21
     defb 211,21,211,60
     defb 211,60,235,71
     defb 235,71,235,10
     defb 171,19,211,21
     defb 172,4,235,10
     defb 172,77,235,71
     defb 171,62,211,60

;;;FRAME #17 80 degrees
     defb 173,20,169,5
     defb 169,5,169,76
     defb 169,76,173,61
     defb 173,61,173,20
     defb 234,9,213,21
     defb 213,21,213,60
     defb 213,60,234,72
     defb 234,72,234,9
     defb 173,20,213,21
     defb 169,5,234,9
     defb 169,76,234,72
     defb 173,61,213,60

;;;FRAME #18 85 degrees
     defb 175,20,166,6
     defb 166,6,166,75
     defb 166,75,175,61
     defb 175,61,175,20
     defb 233,8,215,21
     defb 215,21,215,60
     defb 215,60,233,73
     defb 233,73,233,8
     defb 175,20,215,21
     defb 166,6,233,8
     defb 166,75,233,73
     defb 175,61,215,60

;;;Bytes = 648
i started programming the spectrum when i was 8 :-

1 plot rnd*255,rnd*175
2 goto 1
User avatar
bobs
Microbot
Posts: 107
Joined: Thu Dec 28, 2017 8:26 am
Location: UK
Contact:

Re: ld bc,(hl)

Post by bobs »

@777 You need to put the results of your new calculations back into the original registers, as currently they are left in A and are ignored.

Code: Select all

LD A, 100
SUB C
LD C, A
That’s going to mirror the position about 100 though, is that what you want? Offsetting it might be better?

Code: Select all

LD A, 50
ADD A, C
LD C, A
It also looks from your code that you still need to ensure that those lookup tables are aligned correctly to remove the glitches.
Post Reply