Автор: Graham Mason
Год: 1989
Издатели: Your Sinclair
Языки:
Английский
Формат:
TAP лента
Требования:
ZX Spectrum 48K
Ссылки:
Страница на ZXArt
Страница на World Of Spectrum
Страница на Spectrum Computing
Скриншоты:
Год: 1989
Издатели: Your Sinclair
Языки:
Формат:
Требования:
Ссылки:
Скриншоты:
BORDER FX
by Graham Mason
[The TABLE label in the assembler listing was undefined, but it was]
[pretty obvious where it should go. JimG]
Graham Mason's Border Effects routine is a rather good example of
effective illusion. And it gives a superb impression of how fast
machine code really is.
Using interrupts, the routine changes the border colour in sequence
every 50th of a second. The result is a "solid" bar effect, right in
the border. Take it from me, it's stunning.
I've taken the program apart, split it into sections, and
disembowelled it for your use. I hope it helps you or at least gives a
rough idea of Z80 assembly language.
You'll need an assembler to type in the listing. Any will do. But note
that the '#' before some numbers indicates hexadecimal numbers. Some
assemblers differ in notation. It's best to check the manual first.
This instruction (used in all assemblers) designates the ORiGin address
of your code. In this case it's 60000, although it can be anything between
16384 and 65535.
0000 00000 org 60000
Disables all maskable interrupts and makes the program run slightly faster.
EA60 F3 00000 di
Creates a vector table at 32768 which contains the address the interrupts
jump to every 50th of a second (#9090).
EA61 210080 00000 ld hl,#8000
EA64 110180 00000 ld de,#8001
EA67 010101 00000 ld bc,#0101
EA6A 3690 00000 ld (hl),#90
EA6C EDB0 00000 ldir
Places a jump statement at this address.
EA6E 3EC3 00000 ld a,#c3
EA70 329090 00000 ld (#9090),a
Now at #9090 the interrupt routine is told to jump to the border effects
routine.
EA73 2182EA 00000 ld hl,INTER
EA76 229190 00000 ld (#9091),hl
Points the interrupt register to the high byte of the vector table.
EA79 3E80 00000 ld a,#80
EA7B ED47 00000 ld i,a
Selects interrupt mode two and enables interrupts. The border effects will
start working at this point. IM 2 is the mode allowing you to use your own
interrupting programs in preference to the ROM's.
EA7D ED5E 00000 im 2
EA7F FB 00000 GRAY ei
EA80 18FD 00000 jr GRAY
Saves all registers used on the stack. This must be done at the start of every
routine to prevent corruption.
EA82 F5 00000 INTER push af
EA83 C5 00000 push bc
EA84 E5 00000 push hl
EA85 D5 00000 push de
Border black.
EA86 AF 00000 xor a
EA87 D3FE 00000 out (#fe),a
This delay here is the amount of time the border is off between lines.
EA89 0B 00000 DELAY dec bc
EA8A 78 00000 ld a,b
EA8B B1 00000 or c
EA8C 20FB 00000 jr nz,DELAY
Points HL to the colour table.
EA8E 21F8EA 00000 ld hl,TABLE
Register A holds the contents [pointed to by] HL (that's the next byte from
the table).
EA91 7E 00000 COLLEC ld a,(hl)
Checks to see if the end of the table has been reached (marked by #FF),
if so then branch off to STDATA.
EA92 FEFF 00000 cp #ff
EA94 CAA8EA 00000 jp z,STDATA
Change the border to the colour specified by the table.
EA97 D3FE 00000 out (#fe),a
Register BC holds the amount of time the border colours remain on the screen.
Increase the value for thicker lines.
EA99 010600 00000 ld bc,6
EA9C 0B 00000 DELAY1 dec bc
EA9D 78 00000 ld a,b
EA9E B1 00000 or c
EA9F C29CEA 00000 jp nz,delay1
Clear the Carry flag and loops back until done.
EAA2 E6FF 00000 and #ff
EAA4 23 00000 inc hl
EAA5 C391EA 00000 jp COLLEC
Points HL to the start of the table again.
EAA8 21F8EA 00000 STDATA ld hl,TABLE
Another delay controlling the distance between the top and bottom bars.
The longer the delay the further apart and vice versa.
EAAB 016E07 00000 ld bc,#76e
EAAE 0B 00000 DELAY2 dec bc
EAAF 78 00000 ld a,b
EAB0 B1 00000 or c
EAB1 20FB 00000 jr nz,DELAY2
Register A holds the contents [pointed to by] HL in preparation for "printing"
the second bar. If the end marker appears this time then a key scanning routine
is activated.
EAB3 7E 00000 DATA ld a,(hl)
EAB4 FEFF 00000 cp #ff
EAB6 CACAEA 00000 jp z,KESCAN
Change border.
EAB9 D3FE 00000 out (#fe),a
Another delay, this time for bar two.
A JP instruction is quicker than a JR instruction.
EABB 010600 00000 ld bc,6
EABE 0B 00000 DELAY3 dec bc
EABF 78 00000 ld a,b
EAC0 B1 00000 or c
EAC1 C2BEEA 00000 jp nz,DELAY3
Loop back round until finished.
EAC4 E6FF 00000 and #ff
EAC6 23 00000 inc hl
EAC7 C3B3EA 00000 jp DATA
Scan for SPACE, along the bottom left five keys of the keyboard (coded #7F).
Jump to the rotate routine if space is not pressed.
EACA 3E7F 00000 KESCAN ld a,#7f
EACC DBFE 00000 in a,(#fe)
EACE F6E0 00000 or #e0
EAD0 FEFE 00000 cp #fe
EAD2 200E 00000 jr nz,BACKIN
Turn off the border effect.
EAD4 F3 00000 di
POP the registers off the stack in the reverse order to which they were PUSHED.
EAD5 D1 00000 pop de
EAD6 E1 00000 pop hl
EAD7 C1 00000 pop bc
Set the I register back to normal, in tune with BASIC.
EAD8 3E3F 00000 ld a,#3f
EADA ED47 00000 ld i,a
Re-select the ROM's interrupt mode.
EADC ED56 00000 im 1
Restore A and the flags (F).
EADE F1 00000 pop af
Enable interrupts. Very important when returning to BASIC to prevent "hanging".
EADF FB 00000 ei
Use the ROM error routine, returning with OK 0:1.
EAE0 CF 00000 rst #8
EAE1 FF 00000 defb #ff
This useful routine shifts the contents of the table so that on every
re-print the bars appear to rotate round.
EAE2 3AF8EA 00000 BACKIN ld a,(TABLE)
EAE5 21F9EA 00000 ld hl,TABLE+1
EAE8 11F8EA 00000 ld de,TABLE
EAEB 010D00 00000 ld bc,#d
EAEE EDB0 00000 ldir
EAF0 2B 00000 dec hl
EAF1 77 00000 ld (hl),a
Restore all stacked registers.
EAF2 D1 00000 pop de
EAF3 E1 00000 pop hl
EAF4 C1 00000 pop bc
EAF5 F1 00000 pop af
Return to BASIC with interrupts still running.
EAF6 ED4D 00000 reti
EAF8 06070605 00000 TABLE defb 6,7,6,5,4,3,2,1,1
EAFC 04030201
EB00 01
EB01 01020304 00000 defb 1,2,3,4,5,0,#ff
EB05 0500FF
by Graham Mason
[The TABLE label in the assembler listing was undefined, but it was]
[pretty obvious where it should go. JimG]
Graham Mason's Border Effects routine is a rather good example of
effective illusion. And it gives a superb impression of how fast
machine code really is.
Using interrupts, the routine changes the border colour in sequence
every 50th of a second. The result is a "solid" bar effect, right in
the border. Take it from me, it's stunning.
I've taken the program apart, split it into sections, and
disembowelled it for your use. I hope it helps you or at least gives a
rough idea of Z80 assembly language.
You'll need an assembler to type in the listing. Any will do. But note
that the '#' before some numbers indicates hexadecimal numbers. Some
assemblers differ in notation. It's best to check the manual first.
This instruction (used in all assemblers) designates the ORiGin address
of your code. In this case it's 60000, although it can be anything between
16384 and 65535.
0000 00000 org 60000
Disables all maskable interrupts and makes the program run slightly faster.
EA60 F3 00000 di
Creates a vector table at 32768 which contains the address the interrupts
jump to every 50th of a second (#9090).
EA61 210080 00000 ld hl,#8000
EA64 110180 00000 ld de,#8001
EA67 010101 00000 ld bc,#0101
EA6A 3690 00000 ld (hl),#90
EA6C EDB0 00000 ldir
Places a jump statement at this address.
EA6E 3EC3 00000 ld a,#c3
EA70 329090 00000 ld (#9090),a
Now at #9090 the interrupt routine is told to jump to the border effects
routine.
EA73 2182EA 00000 ld hl,INTER
EA76 229190 00000 ld (#9091),hl
Points the interrupt register to the high byte of the vector table.
EA79 3E80 00000 ld a,#80
EA7B ED47 00000 ld i,a
Selects interrupt mode two and enables interrupts. The border effects will
start working at this point. IM 2 is the mode allowing you to use your own
interrupting programs in preference to the ROM's.
EA7D ED5E 00000 im 2
EA7F FB 00000 GRAY ei
EA80 18FD 00000 jr GRAY
Saves all registers used on the stack. This must be done at the start of every
routine to prevent corruption.
EA82 F5 00000 INTER push af
EA83 C5 00000 push bc
EA84 E5 00000 push hl
EA85 D5 00000 push de
Border black.
EA86 AF 00000 xor a
EA87 D3FE 00000 out (#fe),a
This delay here is the amount of time the border is off between lines.
EA89 0B 00000 DELAY dec bc
EA8A 78 00000 ld a,b
EA8B B1 00000 or c
EA8C 20FB 00000 jr nz,DELAY
Points HL to the colour table.
EA8E 21F8EA 00000 ld hl,TABLE
Register A holds the contents [pointed to by] HL (that's the next byte from
the table).
EA91 7E 00000 COLLEC ld a,(hl)
Checks to see if the end of the table has been reached (marked by #FF),
if so then branch off to STDATA.
EA92 FEFF 00000 cp #ff
EA94 CAA8EA 00000 jp z,STDATA
Change the border to the colour specified by the table.
EA97 D3FE 00000 out (#fe),a
Register BC holds the amount of time the border colours remain on the screen.
Increase the value for thicker lines.
EA99 010600 00000 ld bc,6
EA9C 0B 00000 DELAY1 dec bc
EA9D 78 00000 ld a,b
EA9E B1 00000 or c
EA9F C29CEA 00000 jp nz,delay1
Clear the Carry flag and loops back until done.
EAA2 E6FF 00000 and #ff
EAA4 23 00000 inc hl
EAA5 C391EA 00000 jp COLLEC
Points HL to the start of the table again.
EAA8 21F8EA 00000 STDATA ld hl,TABLE
Another delay controlling the distance between the top and bottom bars.
The longer the delay the further apart and vice versa.
EAAB 016E07 00000 ld bc,#76e
EAAE 0B 00000 DELAY2 dec bc
EAAF 78 00000 ld a,b
EAB0 B1 00000 or c
EAB1 20FB 00000 jr nz,DELAY2
Register A holds the contents [pointed to by] HL in preparation for "printing"
the second bar. If the end marker appears this time then a key scanning routine
is activated.
EAB3 7E 00000 DATA ld a,(hl)
EAB4 FEFF 00000 cp #ff
EAB6 CACAEA 00000 jp z,KESCAN
Change border.
EAB9 D3FE 00000 out (#fe),a
Another delay, this time for bar two.
A JP instruction is quicker than a JR instruction.
EABB 010600 00000 ld bc,6
EABE 0B 00000 DELAY3 dec bc
EABF 78 00000 ld a,b
EAC0 B1 00000 or c
EAC1 C2BEEA 00000 jp nz,DELAY3
Loop back round until finished.
EAC4 E6FF 00000 and #ff
EAC6 23 00000 inc hl
EAC7 C3B3EA 00000 jp DATA
Scan for SPACE, along the bottom left five keys of the keyboard (coded #7F).
Jump to the rotate routine if space is not pressed.
EACA 3E7F 00000 KESCAN ld a,#7f
EACC DBFE 00000 in a,(#fe)
EACE F6E0 00000 or #e0
EAD0 FEFE 00000 cp #fe
EAD2 200E 00000 jr nz,BACKIN
Turn off the border effect.
EAD4 F3 00000 di
POP the registers off the stack in the reverse order to which they were PUSHED.
EAD5 D1 00000 pop de
EAD6 E1 00000 pop hl
EAD7 C1 00000 pop bc
Set the I register back to normal, in tune with BASIC.
EAD8 3E3F 00000 ld a,#3f
EADA ED47 00000 ld i,a
Re-select the ROM's interrupt mode.
EADC ED56 00000 im 1
Restore A and the flags (F).
EADE F1 00000 pop af
Enable interrupts. Very important when returning to BASIC to prevent "hanging".
EADF FB 00000 ei
Use the ROM error routine, returning with OK 0:1.
EAE0 CF 00000 rst #8
EAE1 FF 00000 defb #ff
This useful routine shifts the contents of the table so that on every
re-print the bars appear to rotate round.
EAE2 3AF8EA 00000 BACKIN ld a,(TABLE)
EAE5 21F9EA 00000 ld hl,TABLE+1
EAE8 11F8EA 00000 ld de,TABLE
EAEB 010D00 00000 ld bc,#d
EAEE EDB0 00000 ldir
EAF0 2B 00000 dec hl
EAF1 77 00000 ld (hl),a
Restore all stacked registers.
EAF2 D1 00000 pop de
EAF3 E1 00000 pop hl
EAF4 C1 00000 pop bc
EAF5 F1 00000 pop af
Return to BASIC with interrupts still running.
EAF6 ED4D 00000 reti
EAF8 06070605 00000 TABLE defb 6,7,6,5,4,3,2,1,1
EAFC 04030201
EB00 01
EB01 01020304 00000 defb 1,2,3,4,5,0,#ff
EB05 0500FF