Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Compiuter PlotChat
#1
I am working in this routine pixel-precise.
It is ripped from microhobby and wos forum.
Modified by me. I need help to complete the paint attributes method, because in asm my routine works fine, baut when I passed t sub It fails.
Here is the code.
Modified 20-June-2010 included colour ripped by wos
Modified 21-June-2010 included attributes in the same sub.
Now are two independent subs methods:
1.-PlotChar(file,column,CharAdr)
PlotCharPaint(file,column,atribute)
2.- PlotChat(file,column,CharAdr,atrib)
Probably, this is the last update for this routine.

Modified 2010-07-09 including fastcall and all asm routines embebed. The on ly problem is because the rets in atributes process make me save three bytes in printer buffer. Also I can not use Ubyte in fastcall because I do not understand how it works.
Code:
'========================== '=plotchat=v3.100709======= '========================== 'ripped from microhobby and 'wos forum 'thx to britlion lcd boriel '-------------------------- border 6 cls 'demo of PlotChar Dim YoF,YoC As Ubyte YoF=50:YoC=70 YoCharAdr=@manwen PlotChar(100,200,YoCharAdr) PlotCharPaint(100,200,01101001b) '--- dim w as ubyte w=0 '--- PlotChat((256*32)+512,@manwen,01101001b) do 'char paper7 = 00111010b PlotChat(w,@manwen,00110010b) asm halt ;slow movement end asm PlotChat(w,@manwen,00111010b) w=w+1 ' YoF=YoF+1 loop until w>255 end '=fin====================== FUNCTION FASTCALL PlotChat(paramHL AS Uinteger,paramDE AS Uinteger,paramBC AS Uinteger) asm ;hl-atr de-coord bc-graf ld b,h ;pilla atr,0 ld c,l ;BFActual(0) pop hl ;recup ret pop de ;pilla p2-coord ex (sp),hl ;pilla p3-graf ;--- ;bc-atr de-coord bc-graf ;-------------------------- ;### primera parte ;-------------------------- ;para: ; ld hl,16384 ; ld (hl),a ; jr para ;el atributo viene en L ;en de debe estar manwen ;en bc estan las coords b-row c-col ;descartamos a=pareado del atributo ;--- ;enterramos las coords ld a,c ld (23500),a ld a,b ld (23501),a ;enterramos el atrib para luego ld a,l ld (23502),a ;--- ;comment halt for thrust the movement halt prixoratr: ;-------------------- ;entrada e=dirmemLB 22 ; d=dirmemHB 256*X ; H=pareja del atributo ; L=atributo 33 ; b=coord row 256*X ; c=coord colum 11 ; a=se queda a cero ; 1er byte de la figura? ;-------------------- ; ld e,(IX+7) ;file ; ld d,(IX+5) ;colum ; ld l,(IX+8) ;lowbyte charadr ; ld h,(IX+9) ;highbyte charadr ex de,hl ld d,b ld e,c ld b,8 bucbyt2: ld a,(hl) ;byte del carac push bc ;guar cont bytes ld b,8 bucbit2: push bc ;guar cont bits rla ;desplaza un bit jr nc,noplot2 ;si era 0 no pinta ld b,d ;b=y ;aki va d ld c,e ;c=x ;aki va e push de ;guar regs push hl push af ;aki jamas un halt enlentece mucho call co2 ;hace plot c,b ;pero plotw de mh63 pop af ;recup byte car pop hl ;recup dir del byte pop de ;recup coords noplot2: inc e ;inc x pop bc ;recup cont bits djnz bucbit2 ;prox bit inc d ;dec y pop bc ;recup cont bytes inc hl ;dir del byte ;dec hl ;dir del byte ld a,248 ;a=-8 add a,e ;resta 8 a x ld e,a djnz bucbyt2 ;prox byte ;dec d ;dec d ;dec d ;dec d ;dec d ;dec d ;dec d ;dec d ret ;============ ;MH63PLOTW ;============ ; screen 010VVsss vvvHHHHH ; coords VVxxxvvv HHHHHsss ; objeto 010VVvvv xxxHHHHH sss ; xxx son despreciados ;------------------------ co2: ld b,d ld c,e LD H,40h ;0100-0000 = 16384 LD A,B ;b=x=fila VVxxxvvv AND 7 ;0000-0vvv ADD A,H ;0100-0vvv LD H,A ;aseguramos H ;intermedio SRL B ;0VVxxxvv SRL B ;00VVxxxv SRL B ;000VVxxx LD A,B ;000VVxxx AND 24 ;000VV000 ADD A,H ;010VVvvv LD H,A ;desprecias xxx de la vertical ;fin del primer trabajo B ;--- LD A,B ;000VVxxx AND 7 ;00000xxx RRCA ;x00000xx RRCA ;xx00000x RRCA ;xxx00000 LD L,A ; LD A,C ;c=y=colum HHHHHsss AND 7 ;00000sss LD B,A ;B=00000sss ;el bit ;--- SRL C ;0HHHHHss SRL C ;00HHHHHs SRL C ;000HHHHH LD A,C ;000HHHHH ADD A,L ;xxxHHHHH LD L,A ;la horizontal ;---inicio bucle inversor INC B ;B=00000sss + 1 XOR A ;A=00000000 SCF ;F=xxxx-xxx1 c12: RRA ;A=1000-0000 DJNZ c12 ; limpiamos A = 0000-0000 ; buscamos un pixel ; el SFC mete un 1 al principio ; y RRA corre B veces hacia der ese 1 XOR (HL) ;orea A con dfbyte LD (HL),A ;para no borrar ant XOR (HL) ;en negro pone punto blanco ; OR (HL) ;hace over sobre punto negro ;RET ;----------------- priatr2: ;Ripped from Wos-Turkwel ; ld c,(IX+7) ; ld b,(IX+5) ; ld a,(IX+11) ;desentierro coords push hl ld hl,23500 ld c,(hl) inc hl ld b,(hl) ;desenterramos el atrib inc hl ld a,(hl) pop hl ;use alongside the print_char routine to set Attribute values automatically....... ;on entry BC uses exactly the same Y\X values as the print_char routine and A holds the Atrribute Value to be used. ; ;NB If you don't want to use A this way then set up something like ld a,(nnnn) at the start of the print_attribute routine ;instead and that way you can use your own "Sytem Variable" for printing each time ; ;suggested use: ld a,"A" ; ld bc,184*256+249 ; push bc ; call print_char ; pop bc ; ld a,128+64+5 ; call print_attribute ; ret ; ;alternatively you can integrate this into the print_char routine by looking after BC and A...it doesn't matter which way ;round you use it...char\attributes or attributes\char print_attributew: ld d,0 ld e,a ;transfer Attribute Byte to e for easier use ld a,b cp 192 ret nc ;check Y position and exit if off bottom of screen push bc ;save off Y and X values for later and 248 ld h,22 ld l,a add hl,hl add hl,hl srl c srl c srl c ld b,d add hl,bc ;calculate the correct Attribute Address for the Y\X values ld (hl),e ;set the Attribute - this is ALWAYS set no matter what the valid Y\X values used pop bc ;get the Y and X values back into BC call print_attribute2 ;call the subroutine to see if an adjacent Horizontal Attribute needs to be set ; ld a,b cp 184 ret nc ;check to see if we are at Vertical character 23 - if so then no need to set adjacent Vertical Attribute & Exit routine and 7 ret z ;and don't set the adjacent Vertical Attribute if there's no need to & Exit routine ld a,l add a,32 ld l,a ld a,d adc a,h ld h,a ld (hl),e ;set the Attribute address to the line below - and set the adjacent Vertical Attribute ; ;drop through now into adjacent Horizontal Attribute subroutine - all RETs will now Exit the routine completely ; print_attribute2w: ld a,c cp 248 ret nc ;check to see if we are at Horizontal character 31 - if so then no need to set adjacent Horizontal Attribute and 7 ret z ;and don't set the adjacent Horizontal Attribute if there's no need to inc l ld (hl),e dec l ;increment the Attribute address - set the adjacent horizontal Attribute - then set the Attribute Address back ret end asm end function 'fin del fastcall plotchat '========================== FUNCTION FASTCALL PlotChar(ROWparamHL AS Uinteger,COLparamDE AS Uinteger,ADRparamBC AS Uinteger) asm ;hl-atr de-coord bc-graf ld b,h ;pilla atr,0 ld c,l ;BFActual(0) pop hl ;recup retorno pop de ;pilla p2-coord ex (sp),hl ;pilla p3-graf ;--- ;bc-atr de-coord bc-graf ;-------------------------- ;### primera parte ;-------------------------- ;---entrada---------------- ;ROWparamHL bring C uinteger ;COLparamDE bring E uinteger ;ADRparamBC bring hl uinteger ;-------------------------- prixor: ;-------------------- ;entrada e=columnaDF ; d=filaDF ; hl=dirmem figura ; a=primer byte de figura ; ;-------------------- ld d,c ;row ;ld e,e ;col ;change order row x col ;hl ya viene predicho ;ld l,(IX+8) ;lowbyte charadr ;ld h,(IX+9) ;highbyte charadr ld b,8 bucbyt: ld a,(hl) ;byte del carac push bc ;guar cont bytes ld b,8 bucbit: push bc ;guar cont bits rla ;desplaza un bit jr nc,noplot ;si era 0 no pinta ld b,d ;b=y ;aki va d ld c,e ;c=x ;aki va e push de ;guar regs push hl push af ;aki jamas un halt enlentece mucho call co ;hace plot c,b ;pero plotw de mh63 pop af ;recup byte car pop hl ;recup dir del byte pop de ;recup coords noplot: inc e ;inc x pop bc ;recup cont bits djnz bucbit ;prox bit inc d ;dec y pop bc ;recup cont bytes inc hl ;dir del byte ;dec hl ;dir del byte ld a,248 ;a=-8 add a,e ;resta 8 a x ld e,a djnz bucbyt ;prox byte ;dec d ;dec d ;dec d ;dec d ;dec d ;dec d ;dec d ;dec d ret ;============ ;MH63PLOTW ;============ ; screen 010VVsss vvvHHHHH ; coords VVxxxvvv HHHHHsss ; objeto 010VVvvv xxxHHHHH sss ; xxx son despreciados ;------------------------ co: ld b,d ld c,e LD H,40h ;0100-0000 = 16384 LD A,B ;b=x=fila VVxxxvvv AND 7 ;0000-0vvv ADD A,H ;0100-0vvv LD H,A ;aseguramos H ;intermedio SRL B ;0VVxxxvv SRL B ;00VVxxxv SRL B ;000VVxxx LD A,B ;000VVxxx AND 24 ;000VV000 ADD A,H ;010VVvvv LD H,A ;desprecias xxx de la vertical ;fin del primer trabajo B ;--- LD A,B ;000VVxxx AND 7 ;00000xxx RRCA ;x00000xx RRCA ;xx00000x RRCA ;xxx00000 LD L,A ; LD A,C ;c=y=colum HHHHHsss AND 7 ;00000sss LD B,A ;B=00000sss ;el bit ;--- SRL C ;0HHHHHss SRL C ;00HHHHHs SRL C ;000HHHHH LD A,C ;000HHHHH ADD A,L ;xxxHHHHH LD L,A ;la horizontal ;---inicio bucle inversor INC B ;B=00000sss + 1 XOR A ;A=00000000 SCF ;F=xxxx-xxx1 c1: RRA ;A=1000-0000 DJNZ c1 ; limpiamos A = 0000-0000 ; buscamos un pixel ; el SFC mete un 1 al principio ; y RRA corre B veces hacia der ese 1 XOR (HL) ;orea A con dfbyte LD (HL),A ;para no borrar ant XOR (HL) ;en negro pone punto blanco ; OR (HL) ;hace over sobre punto negro ret end asm end function 'fin del fastcall plotchar '========================== sub PlotCharViaSub(row as ubyte,colum as ubyte, charadr as uinteger) asm halt prixor3: ;-------------------- ;entrada e=columnaDF ; d=filaDF ; hl=dirmem figura ; a=primer byte de figura ; ;-------------------- ld e,(IX+7) ;row ld d,(IX+5) ;colum ld l,(IX+8) ;lowbyte charadr ld h,(IX+9) ;highbyte charadr ld b,8 bucbyt3: ld a,(hl) ;byte del carac push bc ;guar cont bytes ld b,8 bucbit3: push bc ;guar cont bits rla ;desplaza un bit jr nc,noplot3 ;si era 0 no pinta ld b,d ;b=y ;aki va d ld c,e ;c=x ;aki va e push de ;guar regs push hl push af ;aki jamas un halt enlentece mucho call co ;hace plot c,b ;pero plotw de mh63 pop af ;recup byte car pop hl ;recup dir del byte pop de ;recup coords noplot3: inc e ;inc x pop bc ;recup cont bits djnz bucbit3 ;prox bit inc d ;dec y pop bc ;recup cont bytes inc hl ;dir del byte ;dec hl ;dir del byte ld a,248 ;a=-8 add a,e ;resta 8 a x ld e,a djnz bucbyt3 ;prox byte ;dec d ;dec d ;dec d ;dec d ;dec d ;dec d ;dec d ;dec d ret ;============ ;MH63PLOTW ;============ ; screen 010VVsss vvvHHHHH ; coords VVxxxvvv HHHHHsss ; objeto 010VVvvv xxxHHHHH sss ; xxx son despreciados ;------------------------ co3: ld b,d ld c,e LD H,40h ;0100-0000 = 16384 LD A,B ;b=x=fila VVxxxvvv AND 7 ;0000-0vvv ADD A,H ;0100-0vvv LD H,A ;aseguramos H ;intermedio SRL B ;0VVxxxvv SRL B ;00VVxxxv SRL B ;000VVxxx LD A,B ;000VVxxx AND 24 ;000VV000 ADD A,H ;010VVvvv LD H,A ;desprecias xxx de la vertical ;fin del primer trabajo B ;--- LD A,B ;000VVxxx AND 7 ;00000xxx RRCA ;x00000xx RRCA ;xx00000x RRCA ;xxx00000 LD L,A ; LD A,C ;c=y=colum HHHHHsss AND 7 ;00000sss LD B,A ;B=00000sss ;el bit ;--- SRL C ;0HHHHHss SRL C ;00HHHHHs SRL C ;000HHHHH LD A,C ;000HHHHH ADD A,L ;xxxHHHHH LD L,A ;la horizontal ;---inicio bucle inversor INC B ;B=00000sss + 1 XOR A ;A=00000000 SCF ;F=xxxx-xxx1 c13: RRA ;A=1000-0000 DJNZ c13 ; limpiamos A = 0000-0000 ; buscamos un pixel ; el SFC mete un 1 al principio ; y RRA corre B veces hacia der ese 1 XOR (HL) ;orea A con dfbyte LD (HL),A ;para no borrar ant XOR (HL) ;en negro pone punto blanco ; OR (HL) ;hace over sobre punto negro RET end asm end sub '========================== FUNCTION FASTCALL PlotCharPaint(ROWparamHL AS Uinteger,COLparamDE AS Uinteger,ATRparamBC AS Uinteger) asm ;hl-atr de-coord bc-graf ld b,h ;pilla atr,0 ld c,l ;BFActual(0) pop hl ;recup retorno pop de ;pilla p2-coord ex (sp),hl ;pilla p3-graf ;--- ;bc-atr de-coord bc-graf ;-------------------------- ;### primera parte ;-------------------------- ;---entrada---------------- ;ROWparamHL bring C uinteger ;COLparamDE bring E uinteger ;ATRparamBC bring hl uinteger ;-------------------------- priatr: ;Ripped from Wos-Turkwel ld b,c ld c,e ld a,l ;atr ok ;use alongside the print_char routine to set Attribute values automatically....... ;on entry BC uses exactly the same Y\X values as the print_char routine and A holds the Atrribute Value to be used. ; ;NB If you don't want to use A this way then set up something like ld a,(nnnn) at the start of the print_attribute routine ;instead and that way you can use your own "Sytem Variable" for printing each time ; ;suggested use: ld a,"A" ; ld bc,184*256+249 ; push bc ; call print_char ; pop bc ; ld a,128+64+5 ; call print_attribute ; ret ; ;alternatively you can integrate this into the print_char routine by looking after BC and A...it doesn't matter which way ;round you use it...char\attributes or attributes\char print_attribute: ld d,0 ld e,a ;transfer Attribute Byte to e for easier use ld a,b cp 192 ret nc ;check Y position and exit if off bottom of screen push bc ;save off Y and X values for later and 248 ld h,22 ld l,a add hl,hl add hl,hl srl c srl c srl c ld b,d add hl,bc ;calculate the correct Attribute Address for the Y\X values ld (hl),e ;set the Attribute - this is ALWAYS set no matter what the valid Y\X values used pop bc ;get the Y and X values back into BC call print_attribute2 ;call the subroutine to see if an adjacent Horizontal Attribute needs to be set ; ld a,b cp 184 ret nc ;check to see if we are at Vertical character 23 - if so then no need to set adjacent Vertical Attribute & Exit routine and 7 ret z ;and don't set the adjacent Vertical Attribute if there's no need to & Exit routine ld a,l add a,32 ld l,a ld a,d adc a,h ld h,a ld (hl),e ;set the Attribute address to the line below - and set the adjacent Vertical Attribute ; ;drop through now into adjacent Horizontal Attribute subroutine - all RETs will now Exit the routine completely ; print_attribute2: ld a,c cp 248 ret nc ;check to see if we are at Horizontal character 31 - if so then no need to set adjacent Horizontal Attribute and 7 ret z ;and don't set the adjacent Horizontal Attribute if there's no need to inc l ld (hl),e dec l ;increment the Attribute address - set the adjacent horizontal Attribute - then set the Attribute Address back ret end asm end function '========================== '----------------- '------ manwen: asm db 00011000b db 00001010b db 01111110b db 01011000b db 00011000b db 00111100b db 00100100b db 00000000b end asm '--- '==========================
Reply
#2
Wow. With some help from the guys over at WorldOfSpectrum, I've been working on exactly the same thing...

Time for a routine face off! Smile
Reply
#3
I modified my rutine above ripping in wos.
Next step is...
plotchat(x,y,adr,atr)
But this is making problems to me.
Thx for your help.
Reply
#4
*heh* You ran off with the code we were discussing?

I did have a High Res Print working, but I got into discussion over the fastest way to rotate stuff. Also currently, it just works with the character set, which isn't all that useful.
Reply
#5
I spent a few mins tweaking the High Res Print code I had, and posted it.

Hope that helps!
Reply
#6
I updated this routine and I think it is finished.
I see your Hires routine and seems to be very flexible method.
It seems to be very practical routine.
Reply
#7
This seems a little awkward:

Code:
do ...code... w=w+3 loop until w=200

Is that some optimization or better than:
Code:
FOR W=0 to 200 step 3 NEXT W
?

Right now I don't know which one is faster, but my gut tells me a for/next loop ought to be - it's designed to have a loop counter. Boriel recently did some optimizations on FOR/NEXT as well, shaving a few clock cycles.

I also have a weird feeling that asking it to stop when W=200 might be a long wait, since 200 doesn't divide evenly by three. (That is, if you keep adding threes, you get 195,198,201,204... - not W=200 until it's looped right around the byte count...)
Reply
#8
britlion Wrote:This seems a little awkward:

Code:
do ...code... w=w+3 loop until w=200

Is that some optimization or better than:
Code:
FOR W=0 to 200 step 3 NEXT W
?

Right now I don't know which one is faster, but my gut tells me a for/next loop ought to be - it's designed to have a loop counter. Boriel recently did some optimizations on FOR/NEXT as well, shaving a few clock cycles.

I also have a weird feeling that asking it to stop when W=200 might be a long wait, since 200 doesn't divide evenly by three. (That is, if you keep adding threes, you get 195,198,201,204... - not W=200 until it's looped right around the byte count...)
DO...LOOP is the same or faster, because FOR ... NEXT is a more complex loop instruction. Also, if LAST value is 255, you can use DO ... LOOP with a byte counter to avoid overflow, whilst FOR will loop forever:
Code:
DIM i as Ubyte = 0 DO ... i = i + 1 LOOP UNTIL i = 0 : REM YES, with overflow, 0 == 256 (mod 256)
Reply
#9
@Compiuter, why don't you put the ASM context encapsulated into the subroutine? Otherwise, people including your files might experience the same *crash* programandala did when using #INCBIN. Try this:

Code:
SUB PlotChar(file as ubyte,colum as ubyte, charadr as uinteger) ASM halt call prixor END ASM RETURN ASM ... ; prixor code END ASM END SUB
If you're interested, you can __FASTCALL__ your subroutine, which makes is a little faster, and allow using RET directly:
Code:
SUB __FASTCALL__ PlotChar(row as ubyte, colum as ubyte, charaddr as uinteger) ASM pop hl ; ret address pop de ; ld d,(IX+5) ;colum ld e, a ; ld e,(IX+7) ;row ex (sp), hl ; This will exchange ret-address with charaddr in the stack ; ld l,(IX+8) ;lowbyte charaddr ; ld h,(IX+9) ;highbyte charaddr ld b,8 halt // Prixor Code goes here END ASM END SUB
Reply
#10
I was going to suggest the same thing, Boriel.

Compiuter - have a look at the routines in the library wiki for example, or other ones posted here in this forum. I kept all the Machine Code inside the SUB/ END SUB lines, so that they are portable - the code is all inside those boundaries, and they will always work, no matter where they are inserted (with the possible exception of maybe needing a DECLARE earlier in the program).
Reply
#11
I was recoding with fastcall. Big Grin
Reply
#12
Fastcall, officially, allows ONE parameter to be sent, and it arrives already in the registers in the usual format for ZX BASIC.

byte,ubyte arrive in the A register.

integer,uinteger arrive in the HL register.

fixed,long,ulong arrive in DEHL


Here's an example (untested, because I just wrote it here!)
Code:
FUNCTION FASTCALL AddOne (in as uByte) as uByte asm inc A end asm END FUNCTION


What this should do is accept a uByte (or actually, a byte; but it will treat it as an unsigned in and out), and increment it by one (with wraparound of 255+1=0) and return it.

Since this is a fastcall function, the variable "in" arrives in the A register already. Since its return type is uByte, what's in the A register is returned to the calling code.

Does that clear it up?
Reply
#13
Hi

I'm having a bit of trouble testing this routine in order to use in my next game. By the moment, I have these issues:

1) Post says this: PlotChat(file,column,CharAdr,atrib) , but PlotChat only gets 3 parameters, not 4, What I'm missing?
2) Paper and ink: where/how to define them? Using PAPER and INK makes a strange mix of colours.
3) I'm copying from FUNCTION FASTCALL PlotChat(paramHL AS Uinteger,paramDE AS Uinteger,paramBC AS Uinteger) to the end of the routine and saving as plotchat.bas in order to do a #INCLUDE in the code. Is the copy OK or there are more parts that I have to leave? For instance, I think that the following code...

Code:
manwen: asm db 00011000b db 00001010b db 01111110b db 01011000b db 00011000b db 00111100b db 00100100b db 00000000b end asm

... can be deleted, right?

Thanks and regards
Reply
#14
HELLO¡¡¡

2) CHAPTER 16 OF MANUAL BASIC ZX SPECTRUM 48k:


IT´S THE RESULT OF THIS OPERATION:

128 IF FLASH ACTIVATE, 0 WITHOUT FLASH
+
64 IF BRIGHT ACTIVATE, 0 WITHOUT BRIGHT
+
8*PAPER
+
INK

EX: PAPER WHITE AND INK BLUE WITHOUT FLASH AND BRIGHT: 0+0+8*7+1=57

GOOD LUCK!
Reply
#15
You're right... attributes in binary. Thanks!

Cheers
Reply


Forum Jump:


Users browsing this thread: 1 Guest(s)