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 301 online users.
» 0 Member(s) | 300 Guest(s)
Bing

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

 
  New features (XOR, bitwise operators)
Posted by: britlion - 07-16-2010, 08:40 AM - Forum: Wishlist - Replies (8)

Was working for me too.

Boriel, I assume that XOR is used like AND and OR and NOT ?

How about align? I assume it moves code up to the next 256 byte block (staggeringly useful stuff, that).
What's the syntax and working for that?
Does it just leave a blank space?
(Can we work out how much?)
Do we automatically get an @label to reference the point - or do we start the block after the align with one?
How do we work out what page it is? @label/256?

Print this item

  64 Char Print
Posted by: britlion - 07-04-2010, 08:17 PM - Forum: How-To & Tutorials - Replies (11)

Stole this from the same source as the print42 one. [I believe Andrew Owen needs thanks for this!]

Doesn't quite work yet - but I might not have time to play with it before the move, so I thought I'd post it as is, in case someone else wants to play with it.

Issues:
Doesn't seem to like printing anything after the first line (out of memory error)
Not sure if the printat routine works. Ought to, though.

It's probably some simple screwup in the end of line routine or something pointing where it shouldn't after it prints.

(And posting it here means I can't lose it, even if I lose the computer!)

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

SUB print64 (characters$ as String)
asm

LD L,(IX+4)
LD H,(IX+5) ; Get String address of characters$ into HL.

; Load BC with length of string, and move HL to point to first character.
        ld c, (hl)               ; 60020 78
        inc hl                   ; 60021 35
        ld b, (hl)               ; 60022 70
        inc hl                   ; 60023 35

; Test string length. If Zero, exit.
        ld a, c                  ; 60024 121
        or b                     ; 60025 176
        jp z, p64_END         ; 60026 200
        
      
examineChar:
        ld a, (hl)               ; Grab the character
        cp 128                   ; too high to print?
        jr nc, nextChar            ; then we go to next.
        
        cp 22                    ; Is this an AT?
        jr nz, newLine           ; If not, hop to newLine routine.
        ex de, hl                ; Swap DE and HL
        and a                    ; Clear Carry
        ld hl, 2                 ;  
        sbc hl, bc               ; Can we Shorten our string length by 2? If not then at (y,x) doesn't make sense.
        ex de, hl                ; Swap DE and HL back
        jp nc, p64_END        ; If we went negative, there wasn't anything to AT to, so we return.
        
        inc hl                   ; Onto our Y co-ordinate
        ld d, (hl)               ; And load it into D
        dec bc                   ; Shorten our remaining string counter.
        inc hl                   ; Onto the X Co-ordinate
        ld e, (hl)               ; Load it into E
        dec bc                   ; Shorten our remaining string counter
        call p64_test_X        ; Make xy legal 60051 205 53  235
        jr p64_eaa3              ; Go to save coords 60054 24  11

newLine:
        cp 13                    ; Is this a newline character? 60056 254 13
        jr nz, p64_isPrintable   ; If not, hop to testing to see if we can print this 60058 32  13
        ld de, (p64_coords)      ; Get coords 60060 237 91  68  235
        call p64_nxtLine         ; Go to next line.     ; 60064 205 58  235

p64_eaa3:
        ld (p64_coords), de    ; 60067 237 83  68  235
        jr nextChar              ; 60071 24  11
p64_isPrintable:
        cp 31                    ; Bigger than 31? 60073 254 31
        jr c, nextChar           ; If not, get the next one. 60075 56  7  
        push hl                  ; Save position 60077 229
        push bc                  ; Save Count   60078 197
        call p64_PrintChar       ; Call Print SubRoutine 60079 205 189 234
        pop bc                   ; Recover length count  60082 193
        pop hl                   ; Recover Position 60083 225
nextChar:
        inc hl                   ; Point to next character 60084 35
        dec bc                   ; Count off this character 60085 11
        ld a, b                  ; Did we run out? 60086 120
        or c                     ; 60087 177
        jr nz, examineChar       ; If not, examine the next one 60088 32  193
        jp p64_END               ; Otherwise hop to END. 60090 201

;p64_eabb:
;        defb "z$"                ;Original "basic" accessed routine used this variable.
        ;ld a, d                  ; 60091 122
        ;inc h                    ; 60092 36

;p64_eabd:
p64_PrintChar:
        exx                      ; 60093 217
        push hl                  ; Save HL' 60094 229
        exx                      ; 60095 217
        sub 32                   ; Take out 32 to convert ascii to position in charset 60096 214 32
        ld h, 0                  ; 60098 38  0  
        rra                      ; Divide by 2 60100 31
        ld l, a                  ; Put our halved value into HL 60101 111
        ld a, 240                ; Set our mask to LEFT side 60102 62  240
        jr nc, p64_eacc          ; If we didn't have a carry (even #), hop forward. 60104 48  2  
        ld a, 15                 ; If we were ab idd #, set our mask to RIGHT side instead 60106 62  15
p64_eacc:
        add hl, hl               ; 60108 41
        add hl, hl               ; 60109 41
        add hl, hl               ; Multiply our char number by 8 60110 41
        ld de, p64_charset       ; Get our Charset position 60111 17  70  235
        add hl, de               ; And add our character count, so we're now pointed at the first byte of the right character. 60114 25
        exx                      ; 60115 217
        ld de, (p64_coords)      ; 60116 237 91  68  235
        ex af, af'               ; 60120 8  
        call p64_loadAndTest     ; 60121 205 49  235
        ex af, af'               ; 60124 8  
        inc e                    ; 60125 28
        ld (p64_coords), de      ; Put position+1 into coords 60126 237 83  68  235
        dec e                    ; 60130 29
        ld b, a                  ; 60131 71
        rr e                     ; Divide X position by 2 60132 203 27
        ld c, 0                  ; 60134 14  0  
        rl c                     ; Bring carry flag into C (result of odd/even position) 60136 203 17
        and 1                    ; Mask out lowest bit in A 60138 230 1  
        xor c                    ; XOR with C (Matches position RightLeft with Char RightLeft) 60140 169
        ld c, a                  ; 60141 79
        jr z, p64_eaf6           ; If they are both the same, skip rotation. 60142 40  6  
        ld a, b                  ; 60144 120
        rrca                     ; 60145 15
        rrca                     ; 60146 15
        rrca                     ; 60147 15
        rrca                     ; 60148 15 ; Move the mask to the other half of the byte.
        ld b, a                  ; 60149 71
p64_eaf6:
        ld a, d                  ; Get Y coord 60150 122
        sra a                    ; 60151 203 47
        sra a                    ; 60153 203 47
        sra a                    ; Multiply by 8 60155 203 47
        add a, 88                ; 60157 198 88
        ld h, a                  ; Put high byte value for attribute into H. 60159 103
        ld a, d                  ; 60160 122
        and 7                    ; 60161 230 7  
        rrca                     ; 60163 15
        rrca                     ; 60164 15
        rrca                     ; 60165 15
        add a, e                 ; 60166 131
        ld l, a                  ; Put low byte for attribute into l 60167 111
        ld a, (23693)            ; Get permanent Colours from System Variable 60168 58  141 92
        ld (hl), a               ; Write new attribute 60171 119
        
        ld a, d                  ; 60172 122
        and 248                  ; 60173 230 248
        add a, 64                ; 60175 198 64
        ld h, a                  ; 60177 103
        ld a, b                  ; 60178 120
        cpl                      ; 60179 47
        ld e, a                  ; 60180 95
        exx                      ; 60181 217
        ld b, 8                  ; 60182 6   8  
p64_eb18:
        ld a, (hl)               ; 60184 126
        exx                      ; 60185 217
        bit 0, c                 ; 60186 203 65
        jr z, p64_eb22             ; 60188 40  4  
        rrca                     ; 60190 15
        rrca                     ; 60191 15
        rrca                     ; 60192 15
        rrca                     ; 60193 15
p64_eb22: and b                    ; 60194 160
        ld d, a                  ; 60195 87
        ld a, (hl)               ; 60196 126
        and e                    ; 60197 163
        or d                     ; 60198 178
        ld (hl), a               ; 60199 119
        inc h                    ; 60200 36
        exx                      ; 60201 217
        inc hl                   ; 60202 35
        djnz p64_eb18              ; 60203 16  235
        exx                      ; 60205 217
        pop hl                   ; 60206 225
        exx                      ; 60207 217
        ret                      ; 60208 201

p64_loadAndTest:
        ld de, (p64_coords)          ; 60209 237 91  68  235

; SubRoutine to go to legal character position. (60213)
p64_test_X:
        ld a, e                   ; Get column from e
        cp 64                     ; more than 64 ?
        jr c, p64_test_Y            ; If not, then jump over nextline
p64_nxtLine:
        inc d                     ; Move down 1
        ld e, 0                   ; reset x co-ord to zero  
p64_test_Y:
        ld a, d                 ; get Y co-ord
        cp 24                     ; Past 24?
        ret c                     ; Return if not.
        ld d, 0                   ; Rest y co-ord to top of screen.  
        ret                       ; Return.
end asm
p64coords:
asm
p64_coords:
       defb 64;  X Coordinate store  60228 64
       defb 23;  Y Coordinate Store 60229 23

p64_charset:         ; 60230
        
        DEFB 0,2,2,2,2,0,2,0                   ; Space !
        DEFB 0,80,82,7,2,7,2,0                 ; " #
        DEFB 0,37,113,66,114,20,117,32         ; $ %
        DEFB 0,34,84,32,96,80,96,0             ; & '
        DEFB 0,36,66,66,66,66,36,0             ; ( )
        DEFB 0,0,82,34,119,34,82,0             ; * +
        DEFB 0,0,0,0,7,32,32,64                ; , -
        DEFB 0,1,1,2,2,100,100,0               ; . /
        DEFB 0,34,86,82,82,82,39,0             ; 0 1
        DEFB 0,34,85,18,33,69,114,0            ; 2 3
        DEFB 0,87,84,118,17,21,18,0            ; 4 5
        DEFB 0,55,65,97,82,84,36,0             ; 6 7
        DEFB 0,34,85,37,83,85,34,0             ; 8 9
        DEFB 0,0,2,32,0,34,2,4                 ; : ;
        DEFB 0,0,16,39,64,39,16,0              ; < =
        DEFB 0,2,69,33,18,32,66,0              ; > ?
        DEFB 0,98,149,183,181,133,101,0        ; @ A     Changed from   ;0,2,37,87,117,85,53,0            
        DEFB 0,98,85,100,84,85,98,0            ; B C
        DEFB 0,103,84,86,84,84,103,0           ; D E
        DEFB 0,114,69,116,71,69,66,0           ; F G
        DEFB 0,87,82,114,82,82,87,0            ; H I
        DEFB 0,53,21,22,21,85,37,0             ; J K
        DEFB 0,69,71,71,69,69,117,0            ; L M
        DEFB 0,82,85,117,117,85,82,0           ; N O
        DEFB 0,98,85,85,103,71,67,0            ; P Q
        DEFB 0,98,85,82,97,85,82,0             ; R S
        DEFB 0,117,37,37,37,37,34,0            ; T U
        DEFB 0,85,85,85,87,39,37,0             ; V W
        DEFB 0,85,85,37,82,82,82,0             ; X Y
        DEFB 0,119,20,36,36,68,119,0           ; Z [
        DEFB 0,71,65,33,33,17,23,0             ; \ ]
        DEFB 0,32,112,32,32,32,47,0            ; ^ _
        DEFB 0,32,86,65,99,69,115,0            ; £ a
        DEFB 0,64,66,101,84,85,98,0            ; b c
        DEFB 0,16,18,53,86,84,35,0             ; d e
        DEFB 0,32,82,69,101,67,69,2            ; f g
        DEFB 0,66,64,102,82,82,87,0            ; h i
        DEFB 0,20,4,53,22,21,85,32             ; j k
        DEFB 0,64,69,71,71,85,37,0             ; l m
        DEFB 0,0,98,85,85,85,82,0              ; n o
        DEFB 0,0,99,85,85,99,65,65             ; p q
        DEFB 0,0,99,84,66,65,70,0              ; r s
        DEFB 0,64,117,69,69,85,34,0            ; t u
        DEFB 0,0,85,85,87,39,37,0              ; v w
        DEFB 0,0,85,85,35,81,85,2              ; x y
        DEFB 0,0,113,18,38,66,113,0            ; z {
        DEFB 0,32,36,34,35,34,36,0             ; | {
        DEFB 0,6,169,86,12,6,9,6               ; ~ (c)

        
p64_END:
end asm
end sub


DIM n,x,y as uInteger
CLS
FOR n=1 to 1000
y=rnd*23
x=rnd*63
printat64(y, x)
print64 ("ABCDEFGHIJKLMNOPQRSTUVWXYZ"(n MOD 26 TO n MOD 26))
print at 23,0;n;"  y:";y;"  x:";x;"  L:";n MOD 26;":";"ABCDEFGHIJKLMNOPQRSTUVWXYZ"(n MOD 26 TO n MOD 26);" "

NEXT n
END

Print this item

  "Unexpected end of line [NEWLINE]
Posted by: britlion - 06-22-2010, 07:28 PM - Forum: Bug Reports - Replies (2)

I was trying to compile up Programandala's Alien-A program.

If I do zxb --asm Alien-A.bas - it compiles to source code just fine.

If I do the usual -T -B -a --debug-array --debug-memory Alien-A.bas it reports "Alien-A.bas:146: Error: Syntax error. Unexpected end of line [NEWLINE]"

There's nothing on line 146. There aren't any other errors reported.

Code:
asm
; *************************************************************
; Alien-A

; A game for the Sinclair ZX Spectrum.

; Copyright (C) 1986,2010 Marcos Cruz (http://programandala.net)
; License/Licencia/Permesilo:
; http://programandala.net/license

; Alien-A is written in Z80 assembly, but it works the BASIC way:
; UDGs and character resolution movement.

; I hope Alien-A can be useful for someone learning Z80 assembly
; with the ZX Spectrum.

; Alien-A was inspired by a simpler program,
; written in Sinclair Basic and published in the ZX magazine
; (issue 1, pages 14-15, 1983):
; http://microhobby.speccy.cz/zx/revista_zx.htm
; http://microhobby.speccy.cz/zx/zx01/01-14.JPG
; http://microhobby.speccy.cz/zx/zx01/01-15.JPG
; http://microhobby.speccy.cz/zxsf/listados/progs/i/Invasores1.tzx

; *************************************************************
; History

; 1986-04-27
; * First working version.
; 1986-04-30
; * Improved with record, number of landing aliens and different aliens; no more need to press fire.
; 1986-05-04
; * Improved with stars, and new graphics inspired by Star Wars. A shield bar is shown instead of the number of landing aliens.
; 1986-06-04
; * Some bugs fixed.
; 1986-06-14
; * No bugs left. Finished.
; 2010-03-23
; * The original source, in GENS3 format, was edited in order to
;   compile it with Pasmo (http://arrakis.es/~ninsesabe/pasmo/)
;   on Debian GNU/Linux.
; 2010-03-24
; * Several changes in order to make the source easier to read:
;   labeled ROM routines and system variables, renamed labels,
;   new comments...
; * Cursor keys intead of P-O-Q-R; easier for my Dvorak keyboard layout!
; * A bit faster control key routine.
; * The aim can move diagonally.
; 2010-04-07
; * Better pseudo random numbers routine.
; 2010-04-13
; * First draft of a final effect: screen fade.
; 2010-04-14
; * Fixed: the last landing alien didn't caused the sound effect
;   because the shield check was done before it.
; * The sound effects are exchanged: now aliens explode when landing.
; * Final effect: random explosions.
; * Improved: the scenery field appears quickly.
; 2010-04-15
; * Fixed: the aim flickering has been solved.
; * Final effect finished.
; * Improved: two dicker lines in the field lines.
; 2010-04-21
; * Improved: pause between the final effect and the menu, with blank screen.
; 2010-04-24
; * Improved: texts in three languages: English, Esperanto and Spanish.
; * Changed: the bar shield is printed in one single color, and it flashes when short (instead of the text).
; 2010-04-27
; * New character set, designed by Alan Grier (http://www.worldofspectrum.org/infoseekid.cgi?id=001171) in 1986, a bit modified by me.

; *************************************************************
; To do

; Check: Text positions.
; Improve: definable keys.
; Improve: don't print the "score" text every time the score changes.
; Fix: the shooted aliens not always get red. Maybe a emulator issue?

; *************************************************************
; ROM routines
#LINE 81
CHAN_OPEN       EQU 1601h ; open a channel (channel in A)
PR_STRING       EQU 203Ch ; print a string (start in DE, count in BC)
PLOT_SUB        EQU 22E5h ; the plot subroutine (coords in BC)
DRAW            EQU 24BAh ; point of the DRAW_LINE routine
STACK_BC        EQU 2D2Bh ; stack BC register pair
FP_TO_BC        EQU 2DA2h
FP_TO_A         EQU 2DD5h
PRINT_FP        EQU 2DE3h ; print a floating point number

; *************************************************************
; Sytem addresses

VIDEO   EQU 16384
ATTRS   EQU 22528

; *************************************************************
; Sytem constants

VIDEO_LENGHT    EQU 6912
ATTRS_LENGHT    EQU 768
BITMAP_LENGHT   EQU VIDEO_LENGHT-ATTRS_LENGHT
COLUMNS         EQU 32

; *************************************************************
; Sytem variables

; Absolute addresses

CHARS   EQU 23606
ERR_NR  EQU 23610
BORDER  EQU 23624
SEED    EQU 23670
FRAMES  EQU 23672
UDG     EQU 23675
P_FLAG  EQU 23697
ATTR_P  EQU 23693
ATTR_T  EQU 23695

; *************************************************************
; Constants
#LINE 122
ATTR            EQU %00000111 ; white ink, black paper
TRANSPARENT     EQU 8 ; keep the current attribute

OWN_CHARSET     EQU 1 ; compile time flag
MAX_SHIELD      EQU 32
SHIELD_ATTR     EQU %01101000 ; bright, cyan paper

INK_CHR         EQU 16
PAPER_CHR       EQU 17
BRIGHT_CHR      EQU 19
INVERSE_CHR     EQU 20
OVER_CHR        EQU 20
AT_CHR          EQU 22
SPACE_CHR       EQU 32

; *************************************************************
; Languages
#LINE 140
LANGUAGES               EQU 3 ; number of languages
EN                      EQU 0 ; English
EO                      EQU 1 ; Esperanto
ES                      EQU 2 ; Spanish
DEFAULT_LANGUAGE        EQU EN ; English

; *************************************************************
; System init

ENTRY   ;ORG 32768
#LINE 151
        DI

        LD A,2
        CALL CHAN_OPEN

        IF OWN_CHARSET
        LD HL,CHAR_SET-256
        LD (CHARS),HL
        ENDIF

        LD HL,ALIEN_UDGS
        LD (UDG),HL

        LD A,(FRAMES)
;        OR 1 ; make sure it's not zero
        LD (SEED),A

; *************************************************************
; Start

START
        CALL CLS

        LD DE,TITLE_TXT
        LD BC,TITLE_LEN
        CALL PR_STRING
PR_MENU
        CALL CLEAR_MENU
        LD HL,MENU_TXTS
        CALL PR_LANGUAGE_STRING
        LD DE,KEYS_TXT
        LD BC,KEYS_LEN
        CALL PR_STRING
        CALL PR_LANGUAGE

FIRST_INK
        LD A,1 ; blue ink
CHANGE_INK
        PUSH AF ; save the ink
        LD HL,ATTRS+32*3 ; from line 4
        LD DE,ATTRS+32*3+1
        LD BC,16*32-1 ; 16 lines
        LD (HL),A
        LDIR

        LD BC,#0F00 ; wait counter

CHECK_KEYS
        LD A,%10111111 ; keyboard semi row H-J-K-L-ENTER
        IN A,(#FE)
        AND %00010 ; key "L"
        JR NZ,WAIT_KEY_0
RELEASE_L
        LD A,%10111111 ; keyboard semi row H-J-K-L-ENTER
        IN A,(#FE)
        AND %00010 ; key "L"
        JR Z,RELEASE_L
        
        LD A,(LANGUAGE)
        INC A
CHANGE_LANGUAGE
        LD (LANGUAGE),A
        CP LANGUAGES
        JR C,PR_MENU
        POP AF ; sync the stack
        XOR A
        JR CHANGE_LANGUAGE

WAIT_KEY_0
        CALL KEY_0
        JR NZ,CHECK_KEYS_END ; jump if "0" is not pressed
RELEASE_KEY_0
        CALL KEY_0
        JR Z,RELEASE_KEY_0 ; jump until "0" is not pressed
        JR INIT

CHECK_KEYS_END
        DEC BC
        LD A,B
        OR C
        JR NZ,CHECK_KEYS

        POP AF ; restore the ink
        INC A ; next ink color
        CP 8 ; no more ink colors?
        JR Z,FIRST_INK ; then start again
        JR CHANGE_INK

; *************************************************************
; Game init

INIT
        LD HL,0
        LD (SCORE),HL
        LD A,MAX_SHIELD
        LD (SHIELD),A
        LD DE,#0A0F ; line 10, column 15
        LD (AIM_COORDS),DE

        CALL SCENERY
        CALL OVER_1
        CALL NEW_ALIEN

; *************************************************************
; Main loop

        CALL PR_AIM
        CALL PR_ALIEN

MAIN
        CALL RANDOM
        CP (IX+MOVE_PROB)
        JR NC,AIM

        CALL PR_ALIEN

        LD DE,(ALIEN_COORDS)
        CALL RANDOM
        CP (IX+GLIDE_DIR)
        JR C,RIGHT

        ; Alien

        ; Left
        LD A,E
        AND A
        JR NZ,LEFT1
        LD E,32
LEFT1
        DEC E
        AND A
        JR DOWN

RIGHT
        LD A,E
        CP 31
        JR NZ,RIGHT1
        LD E,-1
RIGHT1
        INC E

DOWN
        LD (ALIEN_COORDS),DE
        CALL RANDOM
        CP (IX+DOWN_PROB)
        JR NC,PR_COLOR_ALIEN
        INC D
        LD (ALIEN_COORDS),DE
        LD A,D
        CP 16 ; landing?
        JR NZ,PR_COLOR_ALIEN
        CALL EXPLOSION

        ; Decrement the shield

        XOR A
        CALL CHAN_OPEN
        LD A,(SHIELD)
        DEC A
        LD (SHIELD),A
        LD D,1
        LD E,A
        CALL AT
        LD A," "
        RST #10
        LD A,2
        CALL CHAN_OPEN
        LD A,(SHIELD)
        AND A
        JR Z,GAME_OVER ; no shield left
        CP 6
        JR NZ,OTHER_ALIEN

        ; Almost no shield left

        LD A,SHIELD_ATTR+128 ; add flash
        CALL PR_SHIELD_BAR_A

OTHER_ALIEN
        CALL NEW_ALIEN

PR_COLOR_ALIEN
        CALL RANDOM
        AND %01000111 ; keep the bright and the ink
        OR 1 ; but make sure the ink is not black
        LD (ATTR_T),A
        CALL PR_ALIEN
        LD A,ATTR
        LD (ATTR_T),A

AIM
        CALL KEYS
        CALL FIRE

; Hold

        CALL KEY_0
        JR NZ,RESUME
HOLD_OFF
        CALL KEY_0
        JR Z,HOLD_OFF
HOLD
        CALL KEY_0
        JR NZ,HOLD
HOLD_OFF_2
        CALL KEY_0
        JR Z,HOLD_OFF_2

RESUME
        LD BC,2500
DELAY
        DEC BC
        LD A,B
        OR C
        JR NZ,DELAY

        JP MAIN

; *************************************************************
; Game over

GAME_OVER
        LD DE,(SCORE)
        LD BC,(RECORD)
        LD A,B
        CP D
        JR C,NEW_RECORD
        JR NZ,INVASION
        LD A,E
        CP C
        JR NC,INVASION
NEW_RECORD
        LD (RECORD),DE
        CALL OVER_0
        CALL PR_RECORD

; *************************************************************
; Invasion

INVASION

        CALL OVER_1
        CALL PR_AIM ; erase the aim

        LD A,%00000001 ; blue ink
        CALL CL_ATTR_A
        CALL EXPLOSION_DELAY

        CALL RANDOM
        AND %00000111 ; max 7 explosions
        OR %00000100 ; min 4
        LD B,A

FINAL_EXPLOSION
        PUSH BC
        CALL EXPLOSION_DELAY
        LD A,%01000111 ; bright, white ink
        CALL CL_ATTR_A
        CALL EXPLOSION
        LD A,%00000001 ; blue ink
        CALL CL_ATTR_A
        POP BC
        DJNZ FINAL_EXPLOSION

        CALL EXPLOSION_DELAY
        CALL CLS
        CALL EXPLOSION_DELAY
        CALL EXPLOSION_DELAY

        JP START

; Random delay between explosions

EXPLOSION_DELAY
        PUSH BC
        CALL RANDOM
        OR %0000111
        LD B,A
EXPLOSION_DELAY_1
        PUSH BC
        LD B,8
EXPLOSION_DELAY_2
        DJNZ EXPLOSION_DELAY_2
        POP BC
        DEC BC
        LD A,B
        OR C
        JR NZ,EXPLOSION_DELAY_1
        POP BC
        RET

; *************************************************************
; Keyboard

; Is the key "0" pressed? (flag Z set if pressed)

KEY_0
        LD A,%11101111 ; keyboard semi row 6-7-8-9-0
        IN A,(#FE)
        AND %00001 ; key "0"
        RET

; Control keys

KEYS
AIM_COORDS EQU $+1
        LD DE,0

        LD A,%11101111 ; keyboard semi row 6-7-8-9-0
        IN A,(#FE)
        AND %00100 ; key "8"
        JR NZ,LEFT_KEY
        LD A,E
        CP 30 ; right limit
        JR Z,LEFT_KEY
        INC E

LEFT_KEY
        LD A,%11110111 ; keyboard semi row 5-4-3-2-1
        IN A,(#FE)
        AND %10000 ; key "5"
        JR NZ,UP_KEY
        LD A,E
        CP 1 ; left limit
        JR Z,UP_KEY
        DEC E

UP_KEY
        LD A,%11101111 ; keyboard semi row 6-7-8-9-0
        IN A,(#FE)
        AND %01000 ; key "7"
        JR NZ,DOWN_KEY
        LD A,D
        CP 2 ; up limit
        JR Z,DOWN_KEY
        DEC D

DOWN_KEY
        LD A,%11101111 ; keyboard semi row 6-7-8-9-0
        IN A,(#FE)
        AND %10000 ; key "6"
        JR NZ,KEYS_END
        LD A,D
        CP 14 ; down limit
        JR Z,KEYS_END
        INC D

KEYS_END
        LD HL,(AIM_COORDS)
        LD A,H
        CP D ; has the line changed?
        JR NZ,MOVE_AIM
        LD A,L
        CP E ; has the colum changed?
        RET Z ; return if not
        ; otherwise, go into MOVE_AIM and RET

; *************************************************************
; Aim

; Move the aim
; D = new line
; E = new column

MOVE_AIM
        PUSH DE
        CALL PR_AIM ; this erases the aim
        POP DE
        LD (AIM_COORDS),DE
        JR PR_AIM_DE ; it's faster to jump than to load DE from memory; then RET

; Print the aim

PR_AIM
        LD DE,(AIM_COORDS)
PR_AIM_DE
        PUSH DE
        DEC D
        CALL AT
        LD A,"|"
        RST #10
        POP DE
        PUSH DE
        INC D
        CALL AT
        LD A,"|"
        RST #10
        POP DE
        PUSH DE
        DEC E
        CALL AT
        LD A,"-"
        RST #10
        POP DE
        INC E
        CALL AT
        LD A,"-"
        RST #10
        RET

; Fire

FIRE
        LD DE,(ALIEN_COORDS)
        LD BC,(AIM_COORDS)
        LD A,D
        CP B ; are the lines equal?
        RET NZ
        LD A,E
        CP C ; are the columns equal?
        RET NZ

        CALL AT
        LD A,%01000010 ; bright, black paper, red ink
        LD (ATTR_T),A
        EI
        HALT
        DI
        LD A," "
        RST #10

        LD B,#FF
FIRE_1
        DJNZ FIRE_1
        CALL SHOOT
        LD A,ATTR
        LD (ATTR_T),A
        LD A,8 ; backspace
        RST #10
        LD A,(IX+GRAPHIC)
        RST #10

        LD B,0
        LD C,(IX+POINTS)
        LD HL,(SCORE)
        AND A
        ADC HL,BC
        LD DE,(ALIEN_COORDS)
        LD E,D
        LD D,0
        AND A
        SBC HL,DE
        LD (SCORE),HL
        CALL OVER_0
        CALL PR_SCORE
        CALL OVER_1
        CALL NEW_ALIEN
        JP PR_ALIEN ; and RET

; *************************************************************
; Scenery

; Print the scenery

SCENERY
        CALL CLS

        XOR A ; black paper, black ink
        CALL CL_ATTR_A
        CALL SET_ATTR_A

        CALL STARS
        CALL FIELD

        ; Prith the status line

        CALL PR_SCORE
        CALL PR_RECORD
        CALL BRIGHT_1
        CALL PR_SHIELD
        CALL BRIGHT_0

        ; Color the sky and the field

        LD A,%00000111 ; black paper, white ink
        LD HL,ATTRS+32 ; from the second line
        LD DE,ATTRS+32+1
        LD BC,22*32-1 ; 21 lines
        LD (HL),A
        LDIR
if 0 ; not used any more
        ; Color the status line
        ;LD A,%01111000 ; bright, white paper, black ink
        LD A,%01000111 ; bright, black paper,white ink
        LD HL,ATTRS ; from the top left character
        LD DE,ATTRS+1
        LD BC,1*32-1 ; one line
        LD (HL),A
        LDIR
endif
        JP SET_ATTR ; set the standard attribute and RET

; Print the stars

STARS
        LD B,255 ; stars
STAR
        PUSH BC
RANDOM_Y
        CALL RANDOM
        CP 51 ; min Y coordinate
        JR C,RANDOM_Y
        CP 166 ; max Y coordinate
        JR NC,RANDOM_Y
        PUSH AF
        CALL RANDOM
        LD C,A
        POP AF
        LD B,A
        CALL PLOT_SUB
        POP BC
        DJNZ STAR
        RET

; Print the field

FIELD
        LD BC,0
        CALL PLOT_SUB
        LD C,97
        LD B,50
        LD E,1
        LD D,1
        CALL DRAW
        LD C,255
        LD B,0
        CALL PLOT_SUB
        LD C,97
        LD B,50
        LD E,255
        LD D,1
        CALL DRAW
        LD C,137
        LD B,50
        CALL PLOT_SUB
        LD C,50
        LD B,50
        LD E,1
        LD D,255
        CALL DRAW
        LD C,117
        LD B,50
        CALL PLOT_SUB
        LD C,50
        LD B,50
        LD E,255
        LD D,255
        CALL DRAW
        LD C,127
        LD B,50
        CALL PLOT_SUB
        LD C,0
        LD B,50
        LD E,1
        LD D,255
        CALL DRAW
        LD B,50
        CALL H_LINE
        LD B,47
        CALL H_LINE
        LD B,42
        CALL H_LINE
        LD B,35
        CALL H_LINE
        LD B,24
        CALL H_LINE
        LD B,25
        CALL H_LINE
        LD B,12
        CALL H_LINE
        LD B,11
        CALL H_LINE
        LD B,10

; Draw a horizontal line
; B = Y coordinate

H_LINE
        LD C,0
        CALL PLOT_SUB
        LD C,255
        LD B,0
        LD E,1
        LD D,1
        CALL DRAW
        RET

; *************************************************************
; Screen routines

; Clear the screen

CLS
        XOR A
        OUT (#FE),A
        LD (BORDER),A
        LD HL,VIDEO
        LD DE,VIDEO+1
        LD BC,BITMAP_LENGHT-1
        LD (HL),A
        LDIR

        CALL OVER_0
        CALL SET_ATTR

; Set the attributes to A

CL_ATTR_A
        LD HL,ATTRS
        LD DE,ATTRS+1
        LD BC,ATTRS_LENGHT-1
        LD (HL),A
        LDIR
        RET

; Set the default attribute

SET_ATTR
        LD A,ATTR
SET_ATTR_A
        LD (ATTR_P),A
SET_ATTR_T_A
        LD (ATTR_T),A
        RET

; Graphic over

OVER_0  
        LD A,(P_FLAG)
        AND %11111100
        JR SET_P_FLAG
OVER_1  
        LD A,(P_FLAG)
        OR %00000011
SET_P_FLAG
        LD (P_FLAG),A
        RET

if 0 ; not used

; Graphic flash

FLASH_0  
        LD A,(ATTR_T)
        AND %01111111
        JR SET_ATTR_T_A
FLASH_1  
        LD A,(ATTR_T)
        OR %10000000
        JR SET_ATTR_T_A

endif

; Graphic bright

BRIGHT_0  
        LD A,(ATTR_T)
        AND %10111111
        JR SET_ATTR_T_A
BRIGHT_1  
        LD A,(ATTR_T)
        OR %01000000
        JR SET_ATTR_T_A

; Clear the menu

CLEAR_MENU
        LD D,MENU_LINE
        CALL CLEAR_MENU_LINE
        LD D,MENU_LINE+2
        CALL CLEAR_MENU_LINE
        LD D,MENU_LINE+4
        CALL CLEAR_MENU_LINE
        LD D,MENU_LINE+6
        CALL CLEAR_MENU_LINE
        LD D,MENU_LINE+9
        CALL CLEAR_MENU_LINE
        LD D,MENU_LINE+10
        CALL CLEAR_MENU_LINE
        LD D,MENU_LINE+11
        
CLEAR_MENU_LINE
        LD E,MENU_INDENT
        CALL AT
        LD DE,BL_OPTION_TXT
        LD BC,BL_OPTION_LEN
        JP PR_STRING

; Print the record

PR_RECORD
        LD DE,#000F
        CALL PR_STATUS_ATTR
        LD HL,RECORD_TXTS
        CALL PR_LANGUAGE_STRING
RECORD  EQU $+1
        LD BC,0
        JR PR_NUMBER

; Print the score

PR_SCORE
        LD DE,#0000
        CALL PR_STATUS_ATTR
        LD HL,SCORE_TXTS
        CALL PR_LANGUAGE_STRING
SCORE   EQU $+1
        LD BC,0

; Print the number in BC

PR_NUMBER
        CALL STACK_BC
        CALL PRINT_FP
        LD A,INVERSE_CHR ; inverse...
        RST #10
        LD A,0 ; ...off
        RST #10
        LD A,BRIGHT_CHR ; bright...
        RST #10
        LD A,0 ; ...off
        RST #10
        RET

; Print the attributes of score and record

PR_STATUS_ATTR
        ; DE = coords
        CALL AT
        LD DE,STATUS_ATTR_TXT
        LD BC,STATUS_ATTR_LEN
        JP PR_STRING ; print the string and RET

; Print the shield

PR_SHIELD

        LD A,SHIELD_ATTR
PR_SHIELD_BAR_A
        LD HL,ATTRS + 32*23 ; first attribute's address of the 24th line
        LD DE,ATTRS + 32*23 + 1
SHIELD  EQU $+1
        LD BC,MAX_SHIELD
        DEC BC ; needed in order to store the shield in the former opcode, what is needed in order to preserve A and let the PR_SHIELD entry
        LD (HL),A
        LDIR

PR_SHIELD_TXT

        XOR A
        CALL CHAN_OPEN
        LD A,ATTR
        LD (BORDER),A
        LD DE,0
        CALL AT
        LD HL,SHIELD_TXTS
        CALL PR_LANGUAGE_STRING
        LD A,2
        JP CHAN_OPEN ; and RET

; Print the current language in the menu

PR_LANGUAGE
        CALL AT_LANGUAGE
        LD DE,BL_OPTION_TXT
        LD BC,BL_OPTION_LEN
        CALL PR_STRING
        CALL AT_LANGUAGE
        LD HL,LANGUAGE_TXTS

; Print a message depending on the language

        ; HL = address of the text table
        
PR_LANGUAGE_STRING
LANGUAGE EQU PR_LANGUAGE_STRING+1
        LD A,DEFAULT_LANGUAGE
        LD B,A
        ADD A,B
        ADD A,B ; every element in the table has 3 bytes, so A=A*3
        LD B,0
        LD C,A ; offset into BC
        ADD HL,BC ; point to the text start
        LD (TO_DE),HL
TO_DE   EQU $+2
        LD DE,(0)
        INC HL ; point...
        INC HL ; ...to the text length
        LD A,(HL)
        LD C,A
        JP PR_STRING ; print the string and RET

; Set the cursor at the name of the language in the main menu

AT_LANGUAGE
        LD DE,LANGUAGE_LINE*256+MENU_INDENT

; Set the cursor (coords in D and E)

AT
        LD A,AT_CHR
        RST #10
        LD A,D
        RST #10
        LD A,E
        RST #10
        RET

; *************************************************************
; Alien

; New alien

NEW_ALIEN
        CALL RANDOM
        AND %00011111 ; mask the random column (0-31)
        LD E,A
        LD D,1 ; line
        LD (ALIEN_COORDS),DE

        CALL RANDOM
        CP 64
        JR NC,NEW_ALIEN_2
        LD IX,ALIEN_1
        RET
NEW_ALIEN_2
        CP 128
        JR NC,NEW_ALIEN_3
        LD IX,ALIEN_2
        RET
NEW_ALIEN_3
        CP 192
        JR NC,NEW_ALIEN_4
        LD IX,ALIEN_3
        RET
NEW_ALIEN_4
        LD IX,ALIEN_4
        RET

; Print alien

PR_ALIEN
ALIEN_COORDS EQU $+1
        LD DE,0
        CALL AT
        LD A,(IX+GRAPHIC)
        RST #10
        RET


; *************************************************************
; Sound

; Landing

SHOOT
        LD B,5
SHOOT_1
        PUSH BC
        LD HL,#0300
SHOOT_2
        LD DE,1
        PUSH HL
        PUSH IX
        CALL #03BC ; point of the BEEPER ROM routine (#03B5)
        DI
        POP IX
        POP HL
        LD DE,16
        AND A
        SBC HL,DE
        JR NZ,SHOOT_2
        POP BC
        DJNZ SHOOT_1
        RET

; Explosion

EXPLOSION
        PUSH AF
        PUSH BC
        PUSH HL
        LD HL,2000
        LD B,0
        LD E,20
EXPLOSION_1
        PUSH BC
        LD A,(BORDER)
        SRL A
        SRL A
        SRL A
        SET 4,A
        OUT (#FE),A
        LD B,(HL)
EXPLOSION_2
        NOP
        NOP
        NOP
        DJNZ EXPLOSION_2
        RES 4,A
        OUT (#FE),A
        LD B,(HL)
EXPLOSION_3
        NOP
        NOP
        NOP
        DJNZ EXPLOSION_3
        LD B,E
EXPLOSION_4
        NOP
        NOP
        NOP
        NOP
        DJNZ EXPLOSION_4
        INC E
        INC HL
        POP BC
        DJNZ EXPLOSION_1
        POP HL
        POP BC
        POP AF
        RET

; *************************************************************
; Random

; Return a pseudo-random byte (0-255) in A

RANDOM
        PUSH HL
        PUSH BC
        LD A,(SEED)
        LD B,A
        LD A,(FRAMES)
        LD C,A
        LD A,R
        ADD A,B
        ADD A,C
        ;LD HL,509 ; ROM address with the higher number of different values (166) in 256 bytes
        LD HL,13990 ; ROM address pointing to 256 misc values; somehow its result is better
        LD B,0
        LD C,A
        ADC HL,BC
        LD A,(HL)
        LD (SEED),A
        POP BC
        POP HL
        RET

; *************************************************************
; User Defined Graphics

ALIEN_UDGS

        DEFB %00100001
        DEFB %01100011
        DEFB %11101011
        DEFB %11110111
        DEFB %11111111
        DEFB %11101011
        DEFB %01100011
        DEFB %00100001

        DEFB %01000010
        DEFB %10000001
        DEFB %10011001
        DEFB %11100111
        DEFB %10111101
        DEFB %10011001
        DEFB %10000001
        DEFB %01000010

        DEFB %10000100
        DEFB %11000110
        DEFB %11010111
        DEFB %11101111
        DEFB %11111111
        DEFB %11010111
        DEFB %11000110
        DEFB %10000100

; *************************************************************
; Alien's data

; Field offsets

GRAPHIC         EQU 0 ; alien's UDG number
GLIDE_DIR       EQU 1 ; glide direction degree: 0 (left)...center (127)...rigth (255)
DOWN_PROB       EQU 2 ; probability of the alien going down (0...255) (landing speed)
MOVE_PROB       EQU 3 ; probability of the alien moving (0...255) (general activity)
POINTS          EQU 4 ; points got when the alien is destroyed

; Data

ALIEN_1 DEFB 146 ; UDG
        DEFB 0 ; left gliding
        DEFB 55 ; landing speed
        DEFB 50 ; move probability
        DEFB 100 ; points

ALIEN_2 DEFB 145 ; UDG
        DEFB 127 ; vertical gliding
        DEFB 250 ; landing speed
        DEFB 50 ; move probability
        DEFB 200 ; points

ALIEN_3 DEFB 145 ; UDG
        DEFB 127 ; vertical gliding
        DEFB 20 ; landing speed
        DEFB 200 ; move probability
        DEFB 200 ; points

ALIEN_4 DEFB 144 ; UDG
        DEFB 255 ; right gliding
        DEFB 55 ; landing speed
        DEFB 50 ; move probability
        DEFB 100 ; points

; *************************************************************
; Texts

LANGUAGE_LINE   EQU 17

LANGUAGE_TXTS   DEFW LANGUAGE_EN_TXT
                DEFB LANGUAGE_EN_LEN
                DEFW LANGUAGE_EO_TXT
                DEFB LANGUAGE_EO_LEN
                DEFW LANGUAGE_ES_TXT
                DEFB LANGUAGE_ES_LEN
LANGUAGE_EN_TXT DEFM "Not in English"
LANGUAGE_EN_LEN EQU $-LANGUAGE_EN_TXT
LANGUAGE_EO_TXT DEFM "Ne en Esperanto"
LANGUAGE_EO_LEN EQU $-LANGUAGE_EO_TXT
LANGUAGE_ES_TXT DEFM "No en castellano"
LANGUAGE_ES_LEN EQU $-LANGUAGE_ES_TXT

BL_OPTION_TXT   DEFM "                "
BL_OPTION_LEN   EQU $-BL_OPTION_TXT

STATUS_ATTR_TXT
                DEFB PAPER_CHR,0
                DEFB INK_CHR,7
                DEFB BRIGHT_CHR,1
STATUS_ATTR_LEN EQU $-STATUS_ATTR_TXT

SCORE_TXTS      DEFW SCORE_EN_TXT
                DEFB SCORE_EN_LEN
                DEFW SCORE_EO_TXT
                DEFB SCORE_EO_LEN
                DEFW SCORE_ES_TXT
                DEFB SCORE_ES_LEN
SCORE_EN_TXT    DEFM "Score "
SCORE_EN_LEN    EQU $-SCORE_EN_TXT
SCORE_EO_TXT    DEFM "Poentoj "
SCORE_EO_LEN    EQU $-SCORE_EO_TXT
SCORE_ES_TXT    DEFM "Puntos "
SCORE_ES_LEN    EQU $-SCORE_ES_TXT

RECORD_TXTS     DEFW RECORD_EN_TXT
                DEFB RECORD_EN_LEN
                DEFW RECORD_EO_TXT
                DEFB RECORD_EO_LEN
                DEFW RECORD_ES_TXT
                DEFB RECORD_ES_LEN
RECORD_EN_TXT   DEFM "Record "
RECORD_EN_LEN   EQU $-RECORD_EN_TXT
RECORD_EO_TXT   DEFM "Rikordo "
RECORD_EO_LEN   EQU $-RECORD_EO_TXT
RECORD_ES_TXT   DEFM "Marca "
RECORD_ES_LEN   EQU $-RECORD_ES_TXT

SHIELD_TXTS     DEFW SHIELD_EN_TXT
                DEFB SHIELD_EN_LEN
                DEFW SHIELD_EO_TXT
                DEFB SHIELD_EO_LEN
                DEFW SHIELD_ES_TXT
                DEFB SHIELD_ES_LEN
SHIELD_EN_TXT   DEFM "Shield:"
SHIELD_EN_LEN   EQU $-SHIELD_EN_TXT
SHIELD_EO_TXT   DEFB 96
                DEFM "irmilo:"
SHIELD_EO_LEN   EQU $-SHIELD_EO_TXT
SHIELD_ES_TXT   DEFM "Escudo:"
SHIELD_ES_LEN   EQU $-SHIELD_ES_TXT

KEYS_INDENT     EQU 7
KEYS_TXT        DEFB AT_CHR,MENU_LINE,KEYS_INDENT
                DEFM "5"
                DEFB AT_CHR,MENU_LINE+2,KEYS_INDENT
                DEFM "6"
                DEFB AT_CHR,MENU_LINE+4,KEYS_INDENT
                DEFM "7"
                DEFB AT_CHR,MENU_LINE+6,KEYS_INDENT
                DEFM "8"
                DEFB AT_CHR,MENU_LINE+9,KEYS_INDENT
                DEFM "0"
                DEFB AT_CHR,LANGUAGE_LINE,KEYS_INDENT
                DEFM "L"
KEYS_LEN        EQU $-KEYS_TXT

MENU_TXTS       DEFW MENU_EN_TXT
                DEFB MENU_EN_LEN
                DEFW MENU_EO_TXT
                DEFB MENU_EO_LEN
                DEFW MENU_ES_TXT
                DEFB MENU_ES_LEN

MENU_LINE       EQU 4
MENU_INDENT     EQU 10

MENU_EN_TXT     DEFB AT_CHR,MENU_LINE,MENU_INDENT
                DEFM "Left"
                DEFB AT_CHR,MENU_LINE+2,MENU_INDENT
                DEFM "Down"
                DEFB AT_CHR,MENU_LINE+4,MENU_INDENT
                DEFM "Up"
                DEFB AT_CHR,MENU_LINE+6,MENU_INDENT
                DEFM "Right"
                DEFB AT_CHR,MENU_LINE+9,MENU_INDENT
                DEFM "Play/"
                DEFB AT_CHR,MENU_LINE+10,MENU_INDENT
                DEFM "Halt/"
                DEFB AT_CHR,MENU_LINE+11,MENU_INDENT
                DEFM "Continue"
MENU_EN_LEN     EQU $-MENU_EN_TXT

MENU_EO_TXT     DEFB AT_CHR,MENU_LINE,MENU_INDENT
                DEFM "Maldekstre"
                DEFB AT_CHR,MENU_LINE+2,MENU_INDENT
                DEFM "Malsupre"
                DEFB AT_CHR,MENU_LINE+4,MENU_INDENT
                DEFM "Supre"
                DEFB AT_CHR,MENU_LINE+6,MENU_INDENT
                DEFM "Dekstre"
                DEFB AT_CHR,MENU_LINE+9,MENU_INDENT
                DEFM "Ludi/"
                DEFB AT_CHR,MENU_LINE+10,MENU_INDENT
                DEFM "Haltigi/"
                DEFB AT_CHR,MENU_LINE+11,MENU_INDENT
                DEFM "Pluigi"
MENU_EO_LEN     EQU $-MENU_EO_TXT

MENU_ES_TXT     DEFB AT_CHR,MENU_LINE,MENU_INDENT
                DEFM "Izquierda"
                DEFB AT_CHR,MENU_LINE+2,MENU_INDENT
                DEFM "Abajo"
                DEFB AT_CHR,MENU_LINE+4,MENU_INDENT
                DEFM "Arriba"
                DEFB AT_CHR,MENU_LINE+6,MENU_INDENT
                DEFM "Derecha"
                DEFB AT_CHR,MENU_LINE+9,MENU_INDENT
                DEFM "Jugar/"
                DEFB AT_CHR,MENU_LINE+10,MENU_INDENT
                DEFM "Detener/"
                DEFB AT_CHR,MENU_LINE+11,MENU_INDENT
                DEFM "Continuar"
MENU_ES_LEN     EQU $-MENU_ES_TXT

TITLE_TXT       DEFB AT_CHR,0,5
                DEFB BRIGHT_CHR,1
                DEFM "A  L  I  E  N   -   A"
                DEFB AT_CHR,20,4
                DEFB 127 ; copyright character
                DEFM " 1986, 2010 Marcos Cruz"
                DEFB AT_CHR,21,4
                DEFM "http://programandala.net"
                DEFB BRIGHT_CHR,0
TITLE_LEN       EQU $-TITLE_TXT

; *************************************************************
; Character set

        IF OWN_CHARSET
CHAR_SET        INCBIN alien-a_charset.bin
        ENDIF

; *************************************************************

        END ENTRY ; set the entry point

end asm

Print this item

  Moving
Posted by: britlion - 06-22-2010, 07:02 PM - Forum: ZX Basic Compiler - Replies (21)

Just to let you all know that in a month or two I'll be moving from the USA back to the UK.

This is almost certainly going to limit my ability to play with programming and be around. Sad - most of my stuff is going to be in shipping containers for at least three months. Probably more while I find a job and somewhere to live. So if I disappear, I'm sorry! I'll be back!

Print this item

  Wrong PEEKed value from @label (*solved*)
Posted by: programandala.net - 06-21-2010, 03:50 PM - Forum: Bug Reports - Replies (8)

I have a label beetwen to pieces of machine code data:

Code:
asm
    defb 12,8 ; width and heigth (in characters)
end asm

galeon02Charset:

asm
    defb 0,0,0,0,0,0 ; many graphic data
end asm

I tried to access the first two bytes (before the label) from BASIC, PEEKing the label address plus an offset, but I got strange results. In order to find out the problem, I wrote the following:

Code:
    cls
    dim gal as uinteger
    let gal = @galeon02Charset
    print gal ' prints 36716, OK!
    print gal-2,peek(gal-2) ' prints 36714 and 12, OK!
    print gal-1,peek(gal-1) ' prints 36715 and 8, OK!

    print @galeon02Charset ' prints 36716, OK!
    print @galeon02Charset-2,peek(@galeon02Charset-2) ' prints 36714, 106 !!!
    print @galeon02Charset-1,peek(@galeon02Charset-1) ' prints 36715, 107 !!!

    print @galeon02Charset-2,peek(ubyte,@galeon02Charset-2) ' prints 36714, 106 !!!
    print @galeon02Charset-1,peek(ubyte,@galeon02Charset-1) ' prints 36715, 107 !!!

    print @galeon02Charset-2,peek((@galeon02Charset)-2) ' prints 36714, 106 !!!
    print @galeon02Charset-1,peek((@galeon02Charset)-1) ' prints 36715, 107 !!!

I don't understand why the address of the label is printed with PRINT but returns a wrong value with PEEK. Any issue about the type? But the address of a label is supposed to be uinteger, isn't it?

I don't understand why PEEK works with the uinteger variable, initialized to @label, but doesn't work directly with @label.

Is this a bug or am I missing something?

Print this item

  Wrong #defined calculated value
Posted by: programandala.net - 06-21-2010, 09:57 AM - Forum: Help & Support - Replies (3)

I think there's something I'm missing about the way #define values are calculated, look:

Code:
#define screenFirstCol 0
#define screenLastCol 31
#define borderFirstCol screenFirstCol
#define borderLastCol screenLastCol
#define oWinFirstCol  borderFirstCol+1
#define oWinLastCol borderLastCol-1
' Wrong result, 32 instead of 30:
#define oWinWidth oWinLastCol-oWinFirstCol+1

cls
print "Expected values in cramps:"
print
print "screenFirstCol(0)=";screenFirstCol
print "screenLastCol(31)=";screenLastCol
print "borderFirstCol(0)=";borderFirstCol
print "borderLastCol(31)=";borderLastCol
print "oWinFirstCol(1)=";oWinFirstCol
print "oWinLastCol(30)=";oWinLastCol
' Wrong result, 32 instead of 30:
print "oWinWidth(30)=";oWinWidth

pause 0
stop

What's the problem?

I think #defined values are simple labels calculated by the preprocessor. Is it right? Is there any limit about the depth of the calculated values?

Print this item

  The complex page about DIM
Posted by: programandala.net - 06-20-2010, 11:17 PM - Forum: Documentation - Replies (1)

I've rearranged the DIM page. It is the most complex page I've seen in the wiki.There were double contents here and there, and no clear order. It seems text was pasted from different sources several times. I tried to reorganize the whole into two subheaders (variables and arrays). I think now the order is clearer, and there are no redundant contents. I linked to the mentioned command line options, and to the pragma page (that doesn't exist yet).

May someone take a look and see, if something is missing or wrong in the contents, the order or the headers? Thank you.

Print this item

  BritLion's High Res Print
Posted by: britlion - 06-20-2010, 04:00 PM - Forum: How-To & Tutorials - Replies (18)

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"

Print this item

  "C Nonsense in BASIC"
Posted by: programandala.net - 06-20-2010, 12:22 AM - Forum: Help & Support - Replies (5)

First case

I moved the main loop of my program into a sub, but I forgot to call the sub... so the program had nothing to do after DIMing and LETing some variables. The program returned to Sinclair BASIC with the error "C Nonsense in BASIC" instead of "0 OK".

Then I wrote a test program: just one sub, not called. The program returned to Sinclar BASIC with "0 OK". Strange. So there's something wrong with my program.

If I call the sub, or take its content out of the sub, everything works fine.

Second Case

But then I moved the main loop (out of any sub) to the end of the program... and the same error happened. I suspected two files I'm including, with character sets in assembler format, had something to do.

Here you are schematic versions of both cases:

This one works fine:

Code:
' ....most of the program here......
do
  ' MAIN LOOP
loop

#include "charset1.bas"
#include "charset2.bas"

def sub charset()
' bla bla
end sub
' END OF FILE

But this one simply returns with "Nonsense in basic":

Code:
' ....most of the program here......

#include "charset1.bas"
#include "charset2.bas"

def sub charset()
' bla bla
end sub

do
  ' MAIN LOOP
loop

' END OF FILE

Both included files have the same structure:

Code:
label:
asm
  defb 1,8,86,68,78,78,78,6
  ; hundreds of DEFB
  defb 1,8,86,68,78,78,78,6
end asm

So?

Both cases are not the same, but I suspected the included files are the reason of the strange error in the first case, when there was nothing to exectute; and the fact than the main loop is not found in the second case, and the error is returned.

I kept the main loop at the end of the program and removed the #includes. The program worked fine! Case 2 confirmed.

Then I moved the main loop into a sub but didn't called the sub... The program returned with a "0 OK" message as expected! Case 1 confirmed.

Will it happen with explicit (not #included) ASM sections? Let's see. I added some assembler lines right before the main loop sub, but the message was still "0 OK". It seems the strange behaviour is caused by #including the ASM sections.

Am I doing something wrong? Is there any limitation about the location of ASM sections or its including?

Print this item

  Compiuter PlotChat
Posted by: compiuter - 06-19-2010, 08:12 PM - Forum: How-To & Tutorials - Replies (18)

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
'---
'==========================

Print this item