Sure, no problem. Actually, though, before I give the code I will explain how the graph screen is stored so you can work on things lie sprite routines and advanced drawing.
The graph screen buffer is 768 bytes. Each row (96 pixels) is 12 bytes and there are 64 rows. So to draw at (3,3), you would need to move down to the 4th row (it is indexed at 0) and use a mask of %00010000. To draw the pixel on, use OR logic. To draw it off, invert your mask so that everything except the bit in question is 1 (so you don;t mess with any of the other pixels) and use AND logic. To invert, just use XOR.
Now, for the code, I have some rather optimised code, so it could be pretty confusing, sorry .__. This code doesn't draw the pixel, it just gives you a pointer to the correct byte in plotSScreen and a mask:
; b is X
; c is y
; HL points to byte
; A is the mask
; nc if not computed, c if computed
; DE is not changed
ld a,c ;First we want to check if the coordinates are in range
cp 64 \ ret nc ;C is the Y coordinate, so if C≥64, exit with c reset
ld a,b ;Note that if the coords are negative, they are seen as ≥64 or 96. Pretty snazzy, right?
cp 96 \ ret nc ;Check the X coordinate if B≥96
; I like to be tricky! Note that A has the value of the x coordinate and that I don't change this for the next part of code.
ld l,c ;Now we should take the Y coordinate and multiply it by 12
ld h,0 ;HL is now the value of C
ld b,h ;Now BC is the value of C
add hl,hl ;Double HL. Note that 'add hl,[reg]' is only 1 byte
add hl,bc ;Add BC to HL, now HL=3*BC
add hl,hl ;Double HL, now HL=6*BC
add hl,hl ;Double HL, now HL=12*BC. We just used 4 bytes to multiply by 12. Awesome!
ld b,a ;Now B has the x coordinate
and %11111000 ;I want to divide A by 8 to get the byte offset (8 pixels to a byte). I will just shift A right 3 times, so I need to clear the bottom 3 bits
rrca \ rrca \ rrca ;rrca is 4 cycles and 1 byte, so this took 12 cycles and 3 bytes
or 40h ;slightly faster way to do 'set 6,a'. It happens to be that plotSScreen=9340h and 40h=%01000000
ld c,a ;C is now the byte offset
ld a,b ;A is once again the x coordinate
; This is pretty tricky. I take advantage of the address of plotSScreen to make optimisations.
ld b,93h ;plotSScreen = 9340h This is just me being a hyperoptimiser, sorry
add hl,bc ;Now HL points to the byte that the pixel is located in. Now we need the mask.
and %00000111 ;We mask out everything except the lower 3 bits of A. Now A is 0 to 7 and is the bit offset into the byte.
ld b,a ;B is now the bit offset into the byte
inc b ;
ld a,%00000001 ;A is the mask. We will rotate this right 'B' times.
rrca ;rotate A right.
djnz $-1 ;Decrement B, jump back one byte if it is not zero. rrca happens to be one byte, by the way, but not all instructions are.
scf ;set the carry flag since everything was succesful and we want to return 'c' if it worked, 'nc' if not.
Now if you have this as a subroutine, you can do something like this:
; B is X
; C is Y
; D is the method:
; 0=Pxl-Off. This is also for all values >3
; Returns nz if the pixel is off
; Returns z if the pixel is on
ret nc ;means the pixel was out of bounds
dec d ;if D was 1, it is decremented to 0 so it sets the z flag
and (hl) ;if the bit is ON in the graph, then this returns nz, else z.
cpl ;invert the mask
I hope this helps! These routines are pretty well optimised. I actually have an even more optimised version for both speed and size, but it uses SMC and doesn't handle inverting pixels. I also don't believe I added in out-of-bounds detection. If you are interested:
; B is the x-coordinate
; C is the y-coordinate
; DE not modified
; HL points to the byte the pixel is drawn to
; When using the pixel test method:
; z means pixel off
; nz means pixel on
ld a,3Fh ;7
srl b \ rra ;12 19
srl b \ rra ;12 31
srl b \ rra ;12 43
cpl ;4 47
or d ;4 51
rrca \ rrca ;8 59
ld (Method),a ;13 72
ld a,b ;4 76
ld b,0 ;7 83
ld h,b \ ld l,c ;4 87
add hl,bc ;11 98
add hl,bc ;11 109
add hl,hl ;11 120
add hl,hl ;11 131
ld b,0 ;7 138
or 40h ;7 145
ld c,a ;4 149
add hl,bc ;11 160
add hl,bc ;11 171
.db $CB ;15 186
ret ;10 196 37 bytes
In both cases, if you want to draw to some arbitrary buffer, that can be done, too, with some slight modification. In the latter case, it is only 6 cycles slower and the same size.