Alien-A
Description of the page content
Invaders game for the Sinclair ZX Spectrum, written in Z80 assembly.
I wrote this little game in 1986, as an exercise to remake and improve, in Z80 assembly, a game written in Sinclair BASIC I found in a magazine: the original game (3.47 KiB) was anonymously published by the Spanish ZX magazine, first issue, 1983, pages 14 and 15:
I kept the character by character movement and the UDG s. But I changed the game itself in many ways: In fact the only remaining parts were the landscape and the aim.
In 2010, in order to publish it in programandala.net, I loaded the TAP file with the original source (written with GENS3) into my favourite editor, Vim, and converted it into a simple text file ready to be compiled by Pasmo. But when I felt the old source code in my hands, in a modern format, I couldn't resist the temptation to make some changes...
Screenshots
The menu can be shown in three languages: Spanish, Esperanto and English.
The three different alien ships, in the three languages:
Source code
; *************************************************************
; 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
CHAN_OPEN EQU #1601 ; open a channel (channel in A)
PR_STRING EQU #203C ; print a string (start in DE, count in BC)
PLOT_SUB EQU #22E5 ; the plot subroutine (coords in BC)
DRAW EQU #24BA ; point of the DRAW_LINE routine
STACK_BC EQU #2D2B ; stack BC register pair
FP_TO_BC EQU #2DA2
FP_TO_A EQU #2DD5
PRINT_FP EQU #2DE3 ; 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
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
LANGUAGES EQU 3 ; number of languages
EN EQU 0 ; English
EO EQU 1 ; Esperanto
ES EQU 2 ; Spanish
DEFAULT_LANGUAGE EQU EN
; *************************************************************
; System init
ENTRY ORG 32768
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
Downloads
Executable files
Tape formats:
Snaphot formats: