so today ive been playing around with some assembly in javacpc..
i took some examples from the wiki and chibiakumas site and sorta mixed a few bits
namely the Hardware scrolling byte by byte using the CRTC from the wiki...and chibis hello world..
i worked that out prity easily...
then i wanted to plot a simple diagonal line on a new keypress...
i setup the keypress..then had a look at the firmware calls for origin and plot..and set them up with the de and hl regs..
but im struggling to get it to plot more than once...
so started new just to plot the line... all i want to is a simple line from 0,0 to 100,100...
this is what i came up with.... (yeah yeah im a n00b!)
set_origin equ &bbcc ; de=x hl=y
plot_absolute equ &bbea ; de=x hl=y
org &2000
ld de,0
ld hl,0
call set_origin
ld a,0
jp plot_line
ret
plot_line:
inc de
inc hl
call plot_absolute
inc a
cp 100
ret
jr plot_line
it doesnt seem to 'ComPare' a=100 and just returns after the first plot without looping...
could someone give me a hint of my (probably totally obvious) screw up please? :laugh:
i know theres probably faster ways to do it..but i just need the basics atm!
use "ret z" instead of "ret". ret always returns but you want it to return only if a =100.
http://z80-heaven.wikidot.com/instructions-set:cp
http://z80-heaven.wikidot.com/instructions-set:ret
thanks eto!
but i tried that (you mean in the plot_line ret right?)
..that plots once then does nothing!.. and never returns to basic...
and thanks for the links! ...that site is better for instruction info than what i was looking at!
probably the firmware routine destroys a. then you have to save it, e.g. on the stack.
You always need to check the details of the firmware calls to see which registers are corrupted and which are preserved; GRA PLOT ABSOLUTE kills AF, BC, DE and HL so you're pretty much left with IX/IY (slower to access) unless you use the stack.
And it's generally nicer to count backwards to zero when looping, and if you use B to hold the loop counter you can do the decrement/check/jump in one step with DJNZ.
(of course, don't forget the firmware has a line drawing function, so you don't have to plot every point individually :D )
ld b,100
call plot_line
ret
plot_line:
inc de
inc hl
push hl
push de
push bc
call plot_absolute
pop bc
pop de
pop hl
djnz plot_line
ret
&BBEA GRA PLOT ABSOLUTE
Action: Plots a point at an absolute user coordinate, using the
GRA PLOT indirection
Entry: DE contains the user X-coordinate and HL holds the user
Y-coordinate
Exit: AF, BC, DE and HL are corrupt, and all others are
preserved
You must:
push af
push hl
push de
call plot_absolute
pop de
pop hl
pop af
...
cp 100jr nz,plot_lineretor...cp 100ret z
jr plot_line
thank you both!!
i was just looking at push and pop.. but ..now i see i need to push and pop all the corrupt registers if i want to reuse them.... i forgot about that!
cool... went back to the original stuff i was playing with (line on keypress)... and its working great!
this is what ive got today...i think its not too bad for a first attempt in 30 odd years! (of course i didnt write it all.. most is borrowed like a good scriptkiddy would!)
org &4000
km_read_key equ &bb1b
mc_wait_flyback equ &bd19
scr_set_mode equ &bc0e
txt_output equ &bb5a
txt_invert equ &bb9c
set_origin equ &bbcc ; de=x hl=y
plot_absolute equ &bbea ; de=x hl=y
ld a,1
call scr_set_mode
ld hl,message
call display_message
call newline
call txt_invert
ld hl,message
call display_message
call gfx_origin
loop
call mc_wait_flyback
call update_scroll
call check_keys
halt
halt
jp loop
display_message:
ld a,(hl) ;Print a '255' terminated string
cp 255 ;if A reg = 255 do next line else skip..
ret z ;255 hit.. return to where ya come from!
inc hl
call txt_output
jr display_message
message: db 'Compiled with JavaCPC Z80 Assembler!',255
newline:
ld a,13 ;Carriage return
call txt_output
ld a,10 ;Line Feed
jp txt_output
gfx_origin:
ld de,0
ld hl,0
call set_origin
ret
plot_line:
inc de
inc hl
inc a
push de
push hl
push af
call plot_absolute
pop af
pop hl
pop de
cp 100
ret z
jr plot_line
check_keys:
call km_read_key
ret nc
cp 'P' ; O
jp z,scroll_left
cp 'O' ; P
jp z,scroll_right
cp 'p' ; O
jp z,scroll_left
cp 'o' ; P
jp z,scroll_right
cp 'l'
jp z,plot_line
ret
scroll_left:
ld a,(scroll_adjustment)
xor 1 ;; 0->1->0...
ld (scroll_adjustment),a
or a
ret z
;; get current scroll offset
ld hl,(scroll_offset)
;; update it
dec hl
;; ensure scroll offset is in range &000-&3ff
ld a,h
and &3
ld h,a
;; store new scroll offset. It is now ready to be written to the CRTC.
ld (scroll_offset),hl
ret
scroll_right:
ld a,(scroll_adjustment)
xor 1 ;; 0->1->0...
ld (scroll_adjustment),a
or a
ret z
;; get current scroll offset
ld hl,(scroll_offset)
;; update it
inc hl
;; ensure scroll offset is in range &000-&3ff
ld a,h
and &3
ld h,a
;; store new scroll offset. It is now ready to be written to the CRTC.
ld (scroll_offset),hl
ret
update_scroll:
;; write scroll adjustment
ld a,(scroll_adjustment)
add &f5 ;; This value alternates between &F5 and &F6
;; and controls the horizontal position of the visible
;; area on the monitor display. The effect these
;; values have on the position relies on the reaction
;; of the monitor to the horizontal sync output of
;; the CRTC. So for some monitors this may not result
;; in a smooth scroll as we want. This value may need
;; adjustment for your monitor and CRTC variant.
;;
;; From BASIC try the following two lines to see the
;; screen move, which is the basis of this effect:
;;
;; OUT &BC00,3:OUT &BD00,&F5 and
;; OUT &BC00,3:OUT &BD00,&F6
ld bc,&bc03 ;; select CRTC register 3 (horizontal sync width)
out (c),c
inc b
out (c),a ;; set vertical and horizontal sync widths
ld hl,(scroll_offset)
;; write scroll offset (in CRTC character width units)
ld bc,&bc0c ;; select CRTC register 12
out (c),c
ld b,&bd ;; B = I/O address for CRTC register write
;; combine with scroll base
ld a,(scroll_base)
or h
out (c),a
ld bc,&bc0d ;; select CRTC register 13
out (c),c
ld b,&bd ;; B = I/O address for CRTC register write
out (c),l
ret
scroll_adjustment: defb 0
;; high byte of the screen base address
;; &00 -> screen uses &0000-&3fff
;; &10 -> screen uses &4000-&7fff
;; &20 -> screen uses &8000-&bfff
;; &30 -> screen uses &c000-&ffff
scroll_base: defb &30
;; the scroll offset in CRTC character units
scroll_offset: defw 0
one more question...
is it possible to ensure a register is set to zero when entering the function?
if they are already at 100 on entering the plot_line function (eg from pressing the key again).. they will continue to INC the line..
is it possible to loop inside the function without jumping back to its start...
like i want to set DE and HL when i enter it... but if i JR back they always gonna be reset to the first value..
eg.. something like...
plot_line:
ld de,10
ld hl,0
.....jump back here...
inc de
inc hl
inc a
......push, call plot_absolute, pops...
cp 100
ret z
jr ...back up there^
is that possible? how would i go about that?!
..would i have to set it to jump back to that address where the INC starts?... how can i force the address?!
edit: i think i answed my own question with the jump back to the address....
jr plot_line + 6 ; jump 6 bytes.. past the 2 LDs after plot_line
...i still dont get why it seems 200 long compared to a simple basic plot....
Screenshot 2022-11-23 234505.png
SMH.. forgot the A register! :P
now its working perfect
plot_line:
ld de,100
ld hl,100
ld a,0
inc de
inc hl
inc a
push de
push hl
push af
call plot_absolute
pop af
pop hl
pop de
cp 100
ret z
jr plot_line + 8 ;jump 8 bytes after plot_line..past the 2 16bit and 1 8bit LDs
Screenshot 2022-11-24 000046.png
First of all, I'd avoid doing something like:
Jr plot_line + 6
As it's quite brittle if you need to change the code and the point of using an assembler is to avoid hand calculating all this stuff.
Instead put a suitable label where you want the jump to go to and use that instead. You aren't limited to having only one label at the start of a routine.You may want to come up with a good naming convention for these, or use local labels if your assembler supports them (can't remember if winape does)
Not sure what you mean about being 200 long. But I can't see you initialising A to zero at the start of plot_line, even though you seem to be using this to count how many times to loop. So I'd put money on that being the issue.
oh i can just use another label? :doh:
thanks andy
plot_line:
ld de,100
ld hl,100
ld a,0
plot_return:
inc de
inc hl
inc a
push de
push hl
push af
call plot_absolute
pop af
pop hl
pop de
cp 100
ret z
jr plot_return
that is much easier to work with!
oh wow..moved that hw scroll and plot to my real cpc...
my GBS-8200 really doesnt like them CRTC routines!...yikes...
now i want a real monitor! LOL
Quote from: WacKEDmaN on 15:06, 23 November 22oh wow..moved that hw scroll and plot to my real cpc...
my GBS-8200 really doesnt like them CRTC routines!...yikes...
now i want a real monitor! LOL
have you applied the GBSControl mod?
Quote from: eto on 15:50, 23 November 22Quote from: WacKEDmaN on 15:06, 23 November 22oh wow..moved that hw scroll and plot to my real cpc...
my GBS-8200 really doesnt like them CRTC routines!...yikes...
now i want a real monitor! LOL
have you applied the GBSControl mod?
not entirely! only half way!.. i dont have the external clock setup... (i havent even looked for a module yet)
i tried playing with a few settings in gbs-c.. and got it a bit better..but the blue turned black..and it bounces around alot when it scrolls..flickers with the proper blue at the same time... it also seems to freeze and only sync occasionally if i hold the scroll on
interestingly... the code works fine without gbs-c..just standard gbs8266 firmware handles it fine... ..i guess i really need the rest of the mod! :P
..i know gbc-c works better for some games/demos.. but currently not so well with others..