The following warnings occurred:
Warning [2] Undefined array key 0 - Line: 1677 - File: showthread.php PHP 8.2.31 (Linux)
File Line Function
/inc/class_error.php 157 errorHandler->error
/showthread.php 1677 errorHandler->error_callback
/showthread.php 916 buildtree




Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
BritLion's High Res Print
#1
Here's what I've been playing with. Weird that someone else was looking into it too. I have to thank Turkwel over at the WorldOfSpectrum Forums for a LOT of guidance with this one.

This routine prints a character at pixel position (x,y); optionally with attributes.

0 < x < 254
0 < y < 191

If the character is < 256, it assumes you sent an ascii code, and pulls it from the character set. UDG ascii code characters aren't supported in this version (use the address of the UDG - eg. USR "a" instead). If the number is 256 - 65535, it assumes this is an address for a user defined block of data (a character sprite/udg) and plots this data to the screen instead.

If the attribute byte is zero, attributes are skipped, and the routine just updates pixels. I thought, since 0 is black on black, this wasn't too bad a compromise. Otherwise it adjusts the attributes to the byte given. Note that printing one character can adjust up to four attributes!

Note also that this is not a megafast solution to printing sprites. I'm still looking into that option.

There is a Newer version of this and a "sprite" example posted later in this thread.
Code:
FUNCTION t() as uLong asm DI LD DE,(23674) LD D,0 LD HL,(23672) EI end asm end function SUB HRPrint (x as uByte, y as uByte, char as uInteger, attribute as uByte) 'High res Printing, based on code produced, with thanks, by Turkwel over on the WOS boards. 'Brought to ZX Basic by Britlion, June 2010. asm ld b,(IX+7) ld c,(IX+5) push BC ; save our co-ordinates. ;print_char: ld d,(IX+09) inc d dec d jr z, HRPrint_From_Charset ld e,(IX+08) jp HR_Print HRPrint_From_Charset: ld de,(23606) ld h,0 ld l,(IX+8) ; character add hl,hl add hl,hl add hl,hl add hl,de HR_Print: call HRPat ;convert the Y and X pixel values to the correct Screen Address - Address in DE ld a,8 ;set counter to 8 - Bytes of Character Data to put down HRPrint0: push af ;save off Counter ld a,b cp 192 jr c,HRprint1 pop af jp HRPrintEnd ;don't print character if > 191 - off the bottom of the screen - restore AF and exit Print routine ;[this can be removed if you are keeping tight control of your Y values] HRprint1: push hl push de push de ;save off Address of Character Data, Screen Address, Screen Address ld a,c and 7 ld d,a ;get lowest 3 bits of Screen address ld e,255 ;set up E with the Mask to use - 11111111b = All On ld a,(hl) jr z,HRprint3 ;get a Byte of Character Data to put down - but ignore the following Mask shifting ;if the the X value is on an actual Character boundary i.e. there's no need to shift anything HRprint2: rrca srl e dec d jp nz,HRprint2 ;Rotate the Character Data Byte D times - and Shift the Mask Byte as well, forcing Zeroes into the ;Left hand side. The Mask will be used to split the Rotated Character Data over a Character boundary HRprint3: pop hl ;POP one of the Screen Addresses (formerly in DE) into HL ld d,a ld a,e and d ;or (hl) ld (hl),a ;take the Rotated Character Data, mask it with the Mask Byte and the OR it with what's already on the Screen, ;this takes care of the first part of the Byte ;[remove the OR (HL) if you just want a straight write rather than a merge] inc l ld a,l and 31 jr z,HRprint4 ;Increment the Screen Address and check to see if it's at the end of a line, ;if so then there's no need to put down the second part of the Byte ld a,e cpl and d ;or (hl) ld (hl),a ;Similar to the first Byte, we need to Invert the mask with a CPL so we can put down the second part of the Byte ;in the next Character location ;[again, remove the OR (HL) if you just want a straight write rather than a merge] HRprint4: pop de inc d inc b ;get the Screen Address back into DE, increment the MSB so it points the the Address immediately below ;it and Increment the Y value in B as well ld a,b and 7 call z,HRPat ;now check if the Y value has gone over a Character Boundary i.e. we will need to recalculate the Screen ;Address if we've jumped from one Character Line to another - messy but necessary especially for lines 7 and 15 pop hl inc hl ;get the Address of the Character Data back and increment it ready for the next byte of data pop af dec a jp nz,HRPrint0 ;get the Counter value back, decrement it and go back for another write if we haven't reached the end yet jp HRPrintAttributes ;HRPAT is a subroutine to convert pixel values into an absolute screen address ;On Entry - B = Y Value C = X Value On Exit - DE = Screen Address HRPat: ld a,b srl a srl a srl a ld e,a and 24 or 64 ld d,a ld a,b and 7 add a,d ld d,a ld a,e and 7 rrca rrca rrca ld e,a ld a,c srl a srl a srl a add a,e ld e,a ret HRPrintAttributes: POP BC ; recover our X-Y co-ordinates. ld d,0 ld a,(IX+11) ; attribute and a jr z, HRPrintEnd ; if attribute=0, then we don't do attributes. ld e,a ; pass to e ;transfer Attribute Byte to e for easier use ld a,b cp 192 jr nc, HRPrintEnd ;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 print_attributes1: ld a,c cp 248 jr nc,endPrintAttributes1 ;check to see if we are at Horizontal character 31 - if so then no need to set adjacent Horizontal Attribute and 7 jr z, endPrintAttributes1 ;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 endPrintAttributes1: ; ld a,b cp 184 jr nc, HRPrintEnd ;check to see if we are at Vertical character 23 - if so then no need to set adjacent Vertical Attribute & Exit routine and 7 jr z, HRPrintEnd ;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 ; HRPrintAttribute2: ld a,c cp 248 jr nc, HRPrintEnd ;check to see if we are at Horizontal character 31 - if so then no need to set adjacent Horizontal Attribute and 7 jr z, HRPrintEnd ;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 HRPrintEnd: end asm END SUB CLS PRINT at 15,0;"Routine Test" time=t() FOR y=0 to 100 FOR x=0 to 100 HRPrint(x,y,CODE"2",39) NEXT x NEXT y print (t()-time)/CASt(float,50); " seconds"
Reply


Messages In This Thread

Forum Jump:


Users browsing this thread: 1 Guest(s)