ld bc,(hl)
Re: ld bc,(hl)
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
1 plot rnd*255,rnd*175
2 goto 1
Re: ld bc,(hl)
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
1 plot rnd*255,rnd*175
2 goto 1
Re: ld bc,(hl)
@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.
That’s going to mirror the position about 100 though, is that what you want? Offsetting it might be better?
It also looks from your code that you still need to ensure that those lookup tables are aligned correctly to remove the glitches.
Code: Select all
LD A, 100
SUB C
LD C, A
Code: Select all
LD A, 50
ADD A, C
LD C, A