Welcome, Guest
You have to register before you can post on our site.

Username
  

Password
  





Search Forums

(Advanced Search)

Forum Statistics
» Members: 258
» Latest member: manuelzo75
» Forum threads: 1,074
» Forum posts: 6,434

Full Statistics

Online Users
There are currently 384 online users.
» 0 Member(s) | 382 Guest(s)
Bing, Google

Latest Threads
.tap file code not execut...
Forum: Help & Support
Last Post: Zoran
04-28-2025, 10:59 AM
» Replies: 4
» Views: 189
Exit from more than one l...
Forum: Wishlist
Last Post: Duefectu
04-23-2025, 10:06 PM
» Replies: 3
» Views: 258
put small ASM programs li...
Forum: How-To & Tutorials
Last Post: Zoran
04-18-2025, 02:02 PM
» Replies: 6
» Views: 1,521
Creating +3 Menus - Loadi...
Forum: Help & Support
Last Post: merlinkv
04-16-2025, 02:08 PM
» Replies: 6
» Views: 512
Randomize not very random...
Forum: Help & Support
Last Post: Zoran
04-08-2025, 10:40 AM
» Replies: 4
» Views: 414
Scope rules
Forum: Bug Reports
Last Post: Zoran
04-04-2025, 09:46 AM
» Replies: 2
» Views: 287
Using constants not allow...
Forum: Bug Reports
Last Post: baltasarq
03-19-2025, 10:00 PM
» Replies: 8
» Views: 1,014
404 page not found
Forum: Documentation
Last Post: boriel
03-08-2025, 07:16 PM
» Replies: 5
» Views: 2,852
Spectrum keywords codes
Forum: Bug Reports
Last Post: boriel
03-08-2025, 11:00 AM
» Replies: 1
» Views: 395
ZXodus][Engine
Forum: ZX Basic Compiler
Last Post: boriel
02-19-2025, 11:43 PM
» Replies: 69
» Views: 213,483

 
  42 Character Printing
Posted by: britlion - 02-06-2010, 06:52 AM - Forum: How-To & Tutorials - Replies (9)

The following two subroutines will support 42 character printing. Colour is allowed, but be aware that the characters are NOT guaranteed to fit into an attribute square, and as such, may cause colour clash.

Set colour with the permanent colour statements (ink/paper not in a print line).

The 42 character printing routine maintains its own X,Y coordinates for printing. Printing on all 24 lines is supported.

X values can range from 0 to 41 (0 <= X <= 42) and Y values can range from 0 to 24 (0 <= Y <= 24). Use the printAt42(y,x) call to change the current position of the printing, otherwise successive prints carry on where the last one left off (with runover to the next line, correctly after the 42nd character).

Size is kept to a minimum, because the routine uses the ROM character set and cuts out lines from it in order to reduce to 6 pixels wide; with a couple of exceptions that are improved by being thus defined here. A redesigned character set is possible, but only for about 31 characters, owing to space limitations in the data design.

Characters ARE vertically aligned to the 42 character grid, however. This is not proportional printing. Therefore this routine can be used safely for tables and other such gridded arrangements.

Original routine this is based on was written by Paul Wardle.

printat42 routine

Code:
SUB printat42 (y as uByte, x as uByte)
    POKE @printAt42Coords,x
    POKE @printAt42Coords+1,y
END sub

The main print42 routine, with assembly and documentation
Code:
SUB print42 (characters$ as string)


asm

        POP BC ; Grab this
        POP DE ; Grab the return address                    
        POP HL ; grab our string address
        PUSH DE ; put the return address back where we found it
      
        
        LD C,(HL)
        INC HL
        LD B,(HL)       ; all told, LD BC with the length of the string.

        INC HL          ;Puts HL to the first real character in the string.

        LD A,C
        OR B
        RET Z           ; Is the length of the string 0? If so, quit.

examineChar:
        LD A,(HL)       ; Grab the character at our pointer position
        CP 128          ;Too high to print?
        JR NC, nextChar ; Then we go to the next

        CP 22           ; Is this an AT?
        JR NZ, isNewline ; If not jump over the AT routine to isNewline

isAt:
        EX DE,HL        ; Get DE to hold HL for a moment
        AND A           ; Plays with the flags. One of the things it does is reset Carry.
        LD HL,00002
        SBC HL,BC       ; Subtract length of string from HL.
        EX DE,HL        ; Get HL back from DE
        RET NC          ; If the result WASN'T negative, return. (We need AT to have parameters to make sense)

        INC HL          ; Onto our Y co-ordinate
        LD D,(HL)       ; Put it in D
        DEC BC          ; and move our string remaining counter down one                
        INC HL          ; Onto our X co-ordinate
        LD E,(HL)       ; Put the next one in E
        DEC BC          ; and move our string remaining counter down one
        CALL nxtchar      ; Call routine to shuffle right a char
        JR newline      ; Hop over to

isNewline:
        CP 13           ; Is this character a newline?
        JR NZ,checkvalid     ; If not, jump forward
        

newline:
        LD DE,(63536)
        CALL nxtline       ; move to next line

        LD (63536),DE     ; and go on to next character
        JR nextChar
        
checkvalid:
        CP 31           ; Is character <31?
        JR C, nextChar  ; If not go to next character

prn:    PUSH HL          ; Save our position
        PUSH BC          ; Save our countdown of chars left
        CALL printachar       ; Go print a character
        POP BC           ; Recover our count
        POP HL           ; Recover our position                              
nextChar:
        INC HL           ; Move to the next position
        DEC BC           ; count off a character
        LD A,B
        OR C            ; Did we hit the end of our string? (BC=0?)
        JR NZ, examineChar    ; If not, we need to go look at the next character.
        RET               ; End the print routine        
basicVariableName:
         defb "z$"        ; The name of the variable we are looking at.


; This routine forms the new 6-bit wide characters and
;alters the colours to match the text. The y,x co-ordinates and eight
;bytes of workspace are located at the end of this chunk.
; it starts with the character ascii code in the accumulator

printachar:
        EXX
        PUSH HL ; Store H'L' where we can get it.
        EXX              

       ld c, a    ; Put a copy of the character in C
       ld h, 0    
       ld l, a    ; Put the Character in HL
      
       ld de, whichcolumn-32 ; the character is at least 32, so space = 0th entry.      
       add hl, de         ; HL -> table entry for char.
       ld a, (hl)         ; Load our column slice data from the table.
       cp 32             ; Is it less than 32?
       jr nc, calcChar   ; If so, go to the calculated character subroutine


; This is the special case 'we defined the character in the table' option    
       ld de, characters ; Point DE at our table
       ld l, a             ; Put our character number from our table lookup that's in HL in a
       call mult8         ; multiplies L by 8 and adds in DE [so HL points at our table entry]
       ld b, h            
       ld c, l             ; Copy our character data address into BC
       jr printdata         ; We have our data source, so we print it.

calcChar: ; this is the calculate from the ROM data option
            ; a holds the column kill data
       ld de, 15360         ; Character set-256. We could use CHARS here, maybe; but might not work with a redefiend character set.
       ld l, c             ; Get our character back from C
       call mult8         ; Multiply l by 8 and add to DE. (HL points at the ROM data for our character now)
      
       ld de, workspace  ; Point DE at our 8 byte workspace.
       push de             ; Save it
       exx                 ;
       ld c, a             ; Put our kill column in C'
       cpl                 ; Invert
       ld b, a             ; Put the inverse in B'
       exx                 ;
       ld b, 8             ; 8 bytes to a character loop counter

loop1:
       ld a, (hl)         ; Load a byte of character data
       inc hl             ; point at the next byte
       exx                 ;
       ld e, a             ; Put it in e'
       and c             ; keep the left column block we're using
       ld d, a             ; and put it in d'
       ld a, e             ; grab our original back
       rla                 ; shift it left (which pushes out our unwanted column)
       and b             ; keep just the right block
       or d                 ; mix with the left block
       exx                 ;
       ld (de), a         ; put it into our workspace
       inc de             ; next workspace byte
       djnz loop1         ; go round for our other bytes
    
       pop bc             ; Recover a pointer to our workspace.

printdata:
       call testcoords     ; check our position, and wrap around if necessary. [returns with d=y,e=x]
       inc e             ; Bump along to next co-ordinate
       ld (xycoords), de ; Store our coordinates for the next character
       dec e             ; Bump back to our current one
       ld a, e             ; get x
       sla a             ;  Shift Left Arithmetic - *2
       ld l, a             ; put x*2 into L
       sla a             ; make it x*4
       add a, l             ; (x*2)+(x*4)=6x
       ld l, a             ; put 6x into L [Since we're in a 6 pixel font, L now contains the # of first pixel we're interested in]
       srl a             ; divide by 2
       srl a             ; divide by another 2 (/4)
       srl a             ; divide by another 2 (/8)
       ld e, a             ; Put the result in e (Since the screen has 8 pixel bytes, pixel/8 = which char pos along our first pixel is in)
       ld a, l             ; Grab our pixel number again
       and 7             ; And do mod 8 [So now we have how many pixels into the character square we're starting at]
       push af             ; Save A
       ex af, af'          
       ld a, d             ; Put y Coord into A'
       sra a             ; Divide by 2
       sra a             ; Divide by another 2 (/4 total)
       sra a             ; Divide by another 2 (/8) [Gives us a 1/3 of screen number]
       add a, 88         ; Add in start of screen attributes high byte
       ld h, a             ; And put the result in H
       ld a, d             ; grab our Y co-ord again
       and 7             ; Mod 8 (why? *I thought to give a line in this 1/3 of screen, but we're in attrs here)
       rrca                 ;
       rrca                  
       rrca                 ; Bring the bottom 3 bits to the top - Multiply by 32(since there are 32 bytes across the screen), here, in other words. [Faster than 5 SLA instructions]
       add a, e             ; add in our x coordinate byte to give us a low screen byte
       ld l, a                ; Put the result in L. So now HL -> screen byte at the top of the character
      
       ld a, (23693)     ; ATTR P      Permanent current colours, etc (as set up by colour statements).
       ld e, a             ; Copy ATTR into e
       ld (hl), e         ; Drop ATTR value into screen
       inc hl             ; Go to next position along
       pop af             ; Pull how many pixels into this square we are
       cp 3                 ; It more than 2?
       jr c, hop1         ; No? It all fits in this square - jump changing the next attribute
    
       ld (hl), e         ; 63446 Must be yes - we're setting the attributes in the next square too.
hop1:
       dec hl             ; Back up to last position
       ld a, d             ; Y Coord into A'
       and 248             ; Turn it into 0,8 or 16. (y=0-23)
       add a, 64         ; Turn it into 64,72,80  [40,48,50 Hex] for high byte of screen pos
       ld h, a             ; Stick it in H
       push hl             ; Save it
       exx                 ; Swap registers
       pop hl             ; Put it into H'L'
       exx                 ; Swap Back
       ld a, 8              
hop4:
       push af             ; Save Accumulator
       ld a, (bc)         ; Grab a byte of workspace
       exx                 ; Swap registers
       push hl             ; Save h'l'
       ld c, 0             ; put 0 into c'
       ld de, 1023         ; Put 1023 into D'E'
       ex af, af'         ; Swap AF
       and a             ; Flags on A
       jr z, hop3         ; If a is zero jump forward

       ld b, a             ; A -> B
       ex af, af'         ; Swap to A'F'
hop2:; Slides a byte right to the right position in the block (and puts leftover bits in the left side of c)
       and a             ; Clear Carry Flag
       rra                 ; Rotate Right A
       rr c                 ; Rotate right C (Rotates a carry flag off A and into C)
       scf                 ; Set Carry Flag
       rr d                 ; Rotate Right D
       rr e                 ; Rotate Right E (D flows into E, with help from the carry bit)
       djnz hop2         ; Decrement B and loop back
      
       ex af, af'        
hop3:
       ex af, af'        
       ld b, a            
       ld a, (hl)        
       and d            
       or b                
       ld (hl), a         ; Write out our byte
       inc hl             ; Go one byte right
       ld a, (hl)         ; Bring it in
       and e            
       or c                 ; mix those leftover bits into the next block
       ld (hl), a         ; Write it out again
       pop hl            
       inc h                ; Next line
       exx                
       inc bc              ; Next workspace byte
       pop af            
       dec a             
       jr nz, hop4         ; And go back!
    
       exx                 ; Tidy up
       pop hl             ; Clear stack leftovers
       exx                 ; And...
       ret                 ; Go home.

mult8: ; Multiplies L by 8 -> HL and adds it to DE. Used for 8 byte table vectors.
        ld h, 0            
        add hl, hl        
        add hl, hl        
        add hl, hl          
        add hl, de        
        ret
                    
testcoords:
        ld de, (xycoords)    ; get our current screen co-ordinates (d=y,e=x - little endian)
nxtchar:
        ld a, e             ;
        cp 42             ; Are we >42?
        jr c, ycoord     ; if not, hop forward
nxtline:
       inc d             ; if so, so bump us to the next line down
       ld e, 0             ; and reset x to left edge
ycoord:
        ld a, d             ;
       cp 24             ; are we >24 lines?
       ret c             ; if no, exit subroutine
       ld d, 0             ; if yes, wrap around to top line again.
       ret                 ; exit subroutine
end asm
printAt42Coords:
asm      
xycoords:
        defb 0      ; x coordinate      
        defb 0      ; y coordinate

workspace:
        defb 0      
        defb 0        
        defb 0
        defb 0        
        defb 0         
        defb 0
        defb 0        
        defb 0        
    
; The data below identifies a column in the character to remove. It consists of 1's
; from the left edge. First zero bit is the column we're removing.
; If the leftmost bit is NOT 1, then the byte represents a redefined character position
; in the lookup table.
    
whichcolumn:            
    defb 254         ; SPACE
    defb 254         ; !
    defb 128         ; "
    defb 224         ; #
    defb 128         ; $
    defb 0           ; % (Redefined below)
    defb 1           ; &  (Redefined below)
    defb 128         ; '
    defb 128         ; (
    defb 128         ; )
    defb 128         ; *
    defb 128         ; +
    defb 128         ; ,
    defb 128         ; -
    defb 128         ; .
    defb 128         ; /
    defb 2           ; 0 (Redefined below)
    defb 128       ; 1
    defb 224       ; 2
    defb 224       ; 3
    defb 252       ; 4
    defb 224        ; 5
    defb 224        ; 6
    defb 192       ; 7
    defb 240       ; 8
    defb 240       ; 9
    defb 240       ; :
    defb 240       ; ;
    defb 192       ; <
    defb 240       ; =
    defb 192       ; >
    defb 192       ; ?
    defb 248       ; @
    defb 240       ; A
    defb 240       ; B
    defb 240       ; C
    defb 240       ; D
    defb 240       ; E
    defb 240       ; F
    defb 240       ; G
    defb 240       ; H
    defb 128       ; I
    defb 240       ; J
    defb 192       ; K
    defb 240       ; L
    defb 240       ; M
    defb 248       ; N
    defb 240       ; O
    defb 240       ; P
    defb 248       ; Q
    defb 240       ; R
    defb 240       ; S
    defb 3         ; T
    defb 240       ; U
    defb 240       ; V
    defb 240       ; W
    defb 240       ; X
    defb 4         ; Y
    defb 252       ; Z
    defb 224       ; [
    defb 252       ; \
    defb 240        ; ]    
    defb 252        ; ^
    defb 240        ; _
    defb 240        ; UK Pound (Currency) Symbol
    defb 255        ; a
    defb 128        ; b
    defb 255        ; c    
    defb 255        ; d    
    defb 255        ; e    
    defb 255        ; f    
    defb 255        ; g    
    defb 255        ; h    
    defb 255        ; i    
    defb 255        ; j    
    defb 255        ; k    
    defb 255        ; l    
    defb 255        ; m    
    defb 255        ; n    
    defb 255        ; o    
    defb 255        ; p    
    defb 255        ; q    
    defb 255        ; r    
    defb 255        ; s    
    defb 255        ; t    
    defb 255        ; u    
    defb 255        ; v    
    defb 255        ; w    
    defb 255        ; x    
    defb 255        ; y    
    defb 255        ; z    
    defb 128        ; {
    defb 128        ; |
    defb 255        ; }    
    defb 128        ; ~
    defb 5            ; (c)  end column data
    
    
    
characters:    
    defb 0           ; %            
    defb 0            
    defb 100        
    defb 104        
    defb 16
    defb 44
    defb 76
    defb 0
    
    defb 0              ; &
    defb 32
    defb 80              
    defb 32
    defb 84              
    defb 72            
    defb 52        
    defb 0        
    
    defb 0             ; digit 0
    defb 56
    defb 76         
    defb 84            
    defb 84            
    defb 100        
    defb 56          
    defb 0
    
    defb 0             ; Letter T
    defb 124        
    defb 16
    defb 16          
    defb 16
    defb 16          
    defb 16
    defb 0          
    
    defb 0             ; Letter Y
    defb 68          
    defb 68            
    defb 40
    defb 16         
    defb 16
    defb 16         
    defb 0            
    
    defb 0             ; (c) symbol
    defb 48            
    defb 72            
    defb 180        
    defb 164        
    defb 180                                    
    defb 72            
    defb 48            
    
end asm    
END SUB

A little program to test and demonstrate:
Code:
DIM n as uByte
CLS
PRINT "01234567890123456789012345678901"
FOR n=1 to 6
    printat42(n+1,0)
    INK n
    print42("012345678901234567890123456789012345678901")
NEXT n

Print this item

  Weirdness 4
Posted by: britlion - 01-31-2010, 05:49 AM - Forum: Bug Reports - Replies (1)

Okay, this one is pretty small. It crashes.

Code:
FUNCTION RAND () as uInteger : REM Code by Jon Ritman
    random: REM add 46 bytes to this location to hit the store "Lion"
    asm
    RANDOM:     LD HL,(SEED+2)
                LD D,L
                ADD HL,HL
                ADD HL,HL
                LD C,H
                LD HL,(SEED)
                LD B,H
                RL B
                LD E,H
                RL E
                RL D
                ADD HL,BC
                LD (SEED),HL
                LD HL,(SEED+2)
                ADC HL,DE
                RES 7,H
                LD (SEED+2),HL
                JP M,RANDOM3
                LD HL,SEED
    RANDOM2:    INC (HL)
                    INC HL
                JR Z,RANDOM2
    RANDOM3:    LD HL,(SEED)              
                RET
    SEED:       DB "Lion"
    end asm
    
END FUNCTION
CLS                        
DIM  a as uInteger
    let a=@random
    PRINT a
    let a=a+46
    PRINT a

DIM n as uInteger
DIM result as uByte

FOR n=a to a+4
    LET result=peek n
    print n;"=";result;"=";CHR$ (result)
next n

IF I change the last line to:
Code:
print n;"=";result;"=";CHR$ (76)

It doesn't crash. What's the problem with CHR$(uByte) suddenly?

Can anyone else replicate this?

All I was trying to do was put in a nice shiny new random number generator...

Print this item

  Disassembler
Posted by: britlion - 01-31-2010, 03:34 AM - Forum: ZX Basic Compiler - Replies (4)

Just a thought...but since ZXB is based on python, and the SkoolKit is python, and it has a disassembler built in python...

it would be very cool to have the option of disassembling other people's programs to steal routines from.


<!-- m --><a class="postlink" href="http://www.worldofspectrum.org/forums/showthread.php?t=28326&highlight=disassembler">http://www.worldofspectrum.org/forums/s ... sassembler</a><!-- m -->


Now I have NO clue about python, but to my mind it can't be too difficult to joint the dots there and make ZXB an assembler AND a disassembler all in one.

asm in -> .bin file out and .bin file in to .asm out!?

Print this item

  Logical Bitwise Functions - AND, OR, XOR, NOT
Posted by: britlion - 01-31-2010, 12:21 AM - Forum: How-To & Tutorials - Replies (4)

These items do seem to be quite high on a few people's wish list. I hope they help!

Right now I only know how to use FASTCALL with a single parameter. If anyone knows how standard multi parameter calls work when we get into m/c please let me know. For the moment, these work and are pretty fast, even though AND and OR cheat a little.

Binary NOT (8 bit version)

Code:
FUNCTION FASTCALL bNOT (sentIn as uByte) as uByte
    asm
    CPL
    end asm
END FUNCTION

USAGE: bNOT(byte value or ubyte value)

Binary NOT (16 bit version)
Code:
FUNCTION FASTCALL bNOT (sentIn as uInteger) as uInteger
    asm
    LD a,h
    CPL
    ld h,a
    ld a,l
    CPL
    ld l,a
    end ASM
END FUNCTION

USAGE: bNOT(uInteger value)

How about this as a compromise: A NOT function that does an 8 bit not for any value that fits in 8 bits, a 16 bit NOT for any value that fits in 16 bits, and a 32 bit NOT for any larger value.

Code:
FUNCTION FASTCALL bNOT(sentIn as uLONG) as uLONG
    asm

    LD A,D    
    OR E
    JR Z,word  ; if DE = 0, assume it's NOT a long!
    LD A, D
    CPL
    LD D, A
    LD A,E
    CPL
    LD E,A

word:
    LD A,H
    AND A      ; if H=0 assume it's not 16 bit.
    JR Z, byte
    CPL
    LD H,A

byte:
    LD A,L
    CPL
    LD L,A

    END asm

END Function



Binary AND (8 bit)
Code:
FUNCTION bAND (byte1 as uByte, byte2 as uByte) as uByte
       return bANDHL(byte1*256+byte2)
END function

FUNCTION FASTCALL  bANDHL (HL as uInteger) as uByte
    asm
    LD a,h
    AND l
    end asm
END FUNCTION

USAGE bAND (byte value1, byte value2)
NOTE: Yes, this is one function that calls another. It cheats by putting two 8 bit values into a 16 bit. It's definitely possible to have something better optimized, and if I learn how standard calls work, I'll use that.
In the meantime, this does work.

Binary OR (8 bit)
NOTE: This uses the same sneaky methods as bAND. I'm sure better code will turn up later.
Code:
FUNCTION bOR (byte1 as uByte, byte2 as uByte) as uByte
      return bORHL(byte1*256+byte2)
END function

FUNCTION FASTCALL bORHL (HL as uInteger) as uByte
    asm
    LD a,h
    OR l
    end asm
END FUNCTION
USAGE bOR(byte value,byte value)

Print this item

  Weirdness 3
Posted by: britlion - 01-28-2010, 08:04 AM - Forum: Bug Reports - Replies (14)

Code:
FOR i=0 to 7
    LET charASave(i)=PEEK (23675+i)
    BEEP 1,1
NEXT i

This is a snippet of the same program as previously mentioned. I didn't think it was working right with loops. So, I added a beep. It duly beeps once, clears the screen (with NO cls command) and moves on. If I add a print charASave command, it crashes instead. Shouldn't try to catch it out, I guess.

Boriel, a little while ago,[a version or two back] this was far more stable and predictable...what is going on here?

Best clue I have is that when installing it said something about a newer version being there already. So I uninstalled completely and reinstalled. Is my SDK corrupt?? Is there something completely broken about the 'latest version' on the ftp site?

Am I quietly going insane?

Print this item

  Weirdness MK II
Posted by: britlion - 01-28-2010, 07:39 AM - Forum: Bug Reports - Replies (1)

I seem to be just posting stuff that baffles me. I might work it out, but here we go:

The code is actually sent "AA" as a string right here. It comes back as "nn" apparently. Which is odd.

Code:
CLS
FOR i=0 to 1 step 2: REM Just grab the first two temporarily. Change this for the whole input later!
   LET leftChar = CODE characters$ (i to i)
   LET rightChar = CODE characters$ (i+1 to i+1)
   print leftChar, rightChar
   print CHR$(leftChar), CHR$(rightChar)
   print CHR$(110), CHR$(110)
next i

The really weird thing is the result:

Code:
110     110
q       n
n       n


And a line of corrupted screen a little further down.

That screen corruption has me worried. But the results table implies that CHR$(110) comes out sometimes as "q" and sometimes as "n". I think.

Oh, incidentally, string slicing using string(i) doesn't work again. Have to use string(i TO i); otherwise it insists it's not an array and sulks.

However, string(3) [As a number, not a variable] seems to work just fine.

Print this item

  toUpper and toLower functions
Posted by: britlion - 01-27-2010, 06:09 AM - Forum: How-To & Tutorials - No Replies

Hey all. I'm not anything like a good Z80 programmer, but I'm learning snippets. I wanted a fast way to flip between lower and upper case characters. This can of course be done by +/- 32 to the ascii code. This is of course, the same as setting or resetting bit 5 of the character, which assembly is better at (you could also perhaps use the bAND function listed in How-To). Anyway, I found these two to work. I wasn't sure if resetting the carry flag was necessary or not in all cases, so cleared it to be on the safe side.

Edit:
It is also with wry amusement that I note that Boriel has LCase and UCase functions in his library as well that I hadn't noticed. #include <lcase.bas> (and/or ucase) would let you use them. They lower/upper a whole string. His functions also use OR and AND instead of set and res. Irritatingly, though I was sure that bit set and bit reset instructions ought to be faster...they aren't. According to the documentation I have, OR and AND take 7 T states when run on the accumulator. SET and RES take 8. Even though that's pretty baffling, since OR can be used as a set of many bits, and AND can be used as a reset of many bits in one go - the documentation says they are faster. Boriel's code almost always is going to be better than mine - unless you happen to have a single character as an ascii code instead of a string. I'll leave these here then as potentially useful for dealing with things like Y/N? responses for a single letter.

Code:
REM Change a single character code to lower case
REM Anything except an UPPERCASE letter is returned unchanged.
FUNCTION FASTCALL toLower (letter as uByte) as uByte
    asm
    ;AND A ; clear carry flag (unnecessary)
    CP 65
    RET C
    CP 90
    RET NC
    ; set 5,a (slow)
        OR 32 ; faster
    end asm
END FUNCTION



Code:
REM Change a single character code to Upper Case
REM Anything except a lowercase letter is returned unchanged.
FUNCTION FASTCALL toUpper (letter as uByte) as uByte
    asm
       ; AND A ; Clear carry flag (unnecessary)
    CP 97
    RET C
    CP 122
    RET NC
        ; res 5,a (slow)
        AND 224 ; faster
    end asm    
END FUNCTION

Print this item

  Logical operators bugged? (*solved*)
Posted by: britlion - 01-27-2010, 04:36 AM - Forum: Bug Reports - Replies (3)

I can't see why this doesn't work:

Code:
dim a as uByte

FUNCTION get (capitalise as byte) as uByte
    DIM lastK AS uByte AT 23560: REM LAST_K System VAR
    lastK=0
    DO LOOP until lastK <> 0 : REM Wait for a keypress

    IF capitalise >0 AND lastK >= 97 AND lastK <= 122 THEN:
            LET lastK = lastK - 32
    END IF

    IF capitalise <0 AND lastK >=65 AND lastK <= 90 THEN:
        LET lastK=lastK + 32          
    END IF    
    
    RETURN lastK
END FUNCTION

let a=get(1)

print a,chr$(a)

Without fail this doesn't capitalise the key I pressed. get(-1) should only produce lower case (a-z), get(0) should produce what's pressed (a-Z) and get(1) should produce UPPER case (A-Z). It doesn't seem to be changing it. I've proved the IF works - I think the AND is failing.

I tried
Code:
IF ((capitalise >0 AND lastK >= 97) AND lastK <= 122) THEN:
in order to see if' it's something in the multiple AND options. Any one of the three conditions, without the AND seems to come out true.

Are logical functions misbehaving?

Print this item

  BOLD and ITALIC - Taken out? (*solved*)
Posted by: britlion - 01-26-2010, 09:51 PM - Forum: Bug Reports - Replies (1)

Are BOLD and ITALIC no longer supported?

Code:
PRINT BOLD 1; "TEST"

Doesn't seem to compile as a program:

File "zxb.py", line 243, in <module>
File "zxb.py", line 196, in main
File "ply\yacc.pyc", line 263, in parse
File "ply\yacc.pyc", line 710, in parseopt
File "zxbparser.pyc", line 2921, in p_print_list_elem
File "zxbparser.pyc", line 1558, in make_sentence
File "ast.pyc", line 64, in makenode
ast.NotAnAstError: Object 'BOLD' is not an Ast instance
Build Failed!

Same problem with ITALIC. Are they gone?

Print this item

  @array broken? (*solved*)
Posted by: britlion - 01-23-2010, 05:12 AM - Forum: Bug Reports - Replies (3)

I think something broke in the Array code. (Perhaps in asm function _ARRAY ?)

Code:
DIM udg(7) AS uByte => {24,88,126,26,120,72,206,2}
POKE UINTEGER 23675,@udg(0): REM udg(0) is the 1st array element
PRINT @udg(0)

STOP

This code crashes the spectrum - without any reference to @udg, it runs perfectly; so it seems to be the @udg calculation that is breaking.

ZXB 1.2.4.

Print this item