On Thu, 16 Jul 2020 00:29:23 -0700 (PDT), Groo Vee wrote:
There was a game, I'm _99%_ certain it was called Treasure Island, which
had the top half of the screen blue and the bottom black (or maybe it
was the other way around) INCUDING THE BORDER!! ie. the ENTIRE SCREEN'S
TOP HALF was blue!!! This continued WHILE YOU PLAYED THE GAME!!!!!! It
blew my mind at the time, so today, so many years later, I'd love to
know how the HELL they pulled that off? What's going on?
Maskable interrupt handler [1], typically of the IM2 type (vectored
interrupt) where - as opposed to the first example in [1] - the complete
table is filled with #FEFE, so your interrupt handler always starts at
address #FEFE, no matter what lower byte is provided by the "peripheral
device" on the bus (since there usually is none or some Kempston joystick interface producing garbage).
At #FEFE you would then have
ORG #FEFE
; no need to di, Z80 does this automatically
push af ; save carry flag
push bc ; save bc register
set border to blue
ld a,#01 ; blue border
out (#FE),a ; change color
and wait a multiple of 48+176=224 T-States [2]
ld bc,6408h
wait: nop ; 4T
nop ; 4T
nop ; 4T
dec bc ; 6T
jp nc, wait ; 10T
; 28T for each loop, so 8 iterations gets you down one scan line
then change the border color to black
ld a,00h ; black border
out (FEh),a ; change color
, restore the registers and return from the interrupt handler
pop bc ; restore bc
pop af ; restore af
ei ; re-enable interrupts
reti ; return
Hint: Don't ever use HALT in an interrupt handler and stay away from
contended memory (everything below #8000 is managed by the ULA). Have a
look at R. Zak's book "Programming the Z80" for details on machine code
timing [3].
Of course the example above is far from perfect (needs some nudging back
and forth to perfectly syncronize with the start of a scanline, you could
use OUTI/OTIR for even crazier stuff) and you can do this not only to the border, but also the attribute area (using LDI/LDIR), getting you
multicolored attributes that overcome the 8x8 pixel limit.
This is what I wrote, decades ago. It even returns you to ZX BASIC with the highres attributes on.
10 CLEAR 65369
20 LET d=65370
30 FOR a=1 TO 33
40 LET c=0
50 READ a$
60 READ check
70 FOR e=1 TO 10 STEP 2
80 LET b=(CODE a$(e)-48-(7 AND CODE a$(e)>57))*16
90 LET b=b+CODE a$(e+1)-48-(7 AND CODE a$(e+1)>57)
100 PRINT AT 10,0;d,b,: POKE d,b: LET d=d+1: LET c=c+b: NEXT e
110 IF d>65535 THEN GO TO 160
120 IF c<>check THEN PRINT "CHECKSUMERROR IN LINE ";(a-1)*10+9000: LET f=(a-1)*10+9000: LIST f: STOP
130 NEXT a
140 CLS : PRINT "HIGHRESOLUTION COLOUR ATTRIBUTES"'''
150 PRINT "START:",65370'"LENGTH:",166'"INTERRUPT ON:",65370'"INTERRUPT OFF:",65384'''"LABELS:"'"STARTLN:",65393;" L=1"'"DEPTH:",65394;" L=1"'"HIATT:",65395;" L=2"'"IHANDLE:",65524
160 STOP
170 SAVE *"m";1;"HIGHRES-I"CODE 65370,166: VERIFY *"m";1;"HIGHRES-I"CODE
180 STOP
9000 DATA "F321FFFF36",840
9010 DATA "183E3BED47",453
9020 DATA "ED5EFBC9F3",1026
9030 DATA "3E3FED47ED",670
9040 DATA "56FBC90018",562
9050 DATA "0000000000",0
9060 DATA "00C5D5E5F5",884
9070 DATA "ED7375FF31",773
9080 DATA "79FF011802",403
9090 DATA "0B78B120FB",591
9100 DATA "3A71FF8787",696
9110 DATA "87CAA0FF06",758
9120 DATA "0F10FE0000",285
9130 DATA "C83DC295FF",859
9140 DATA "6F3A71FF67",640
9150 DATA "CB3CCB1DCB",698
9160 DATA "3CCB1DCB3C",555
9170 DATA "CB1D110C58",349
9180 DATA "19EB2A73FF",672
9190 DATA "3A72FF0140",492
9200 DATA "00D5EDA0ED",847
9210 DATA "A0EDA0EDA0",954
9220 DATA "EDA0EDA0ED",1031
9230 DATA "A0EDA0D1E2",992
9240 DATA "DBFF180000",498
9250 DATA "E6FF18E4EB",972
9260 DATA "0E2009EB3D",351
9270 DATA "C2BCFFED7B",997
9280 DATA "75FFF1E1D1",1047
9290 DATA "C1FBC33800",695
9300 DATA "00000000F3",243
9310 DATA "C379FF0000",571
9320 DATA "0000000000",0
9330 DATA "0000000000",0
9340 DATA "0000000000",0
which disassembles as (no warrantee, no comments):
ORG 0FF5Ah
DI
LD HL,0FFFFh
LD (HL),18h
LD A,3Bh
LD I,A
IM 2
EI
RET
LFF68: DI
LD A,3Fh
LD I,A
IM 1
EI
RET
LFF71: NOP
LFF72: JR LFF74
LFF74: NOP
LFF75: NOP
NOP
NOP
NOP
LFF79: PUSH BC
PUSH DE
PUSH HL
PUSH AF
LD (LFF75),SP
LD SP,0FF79h
LD BC,0218h
LFF87: DEC BC
LD A,B
OR C
JR NZ,LFF87
LD A,(LFF71)
ADD A,A
ADD A,A
ADD A,A
JP Z,LFFA0
LFF95: LD B,0Fh
LFF97: DJNZ LFF97
NOP
NOP
RET Z
DEC A
JP NZ,LFF95
LFFA0: LD L,A
LD A,(LFF71)
LD H,A
SRL H
RR L
SRL H
RR L
SRL H
RR L
LD DE,580Ch
ADD HL,DE
EX DE,HL
LD HL,(LFF72+1)
LD A,(LFF72)
LFFBC: LD BC,0040h
LFFBF: PUSH DE
LDI
LDI
LDI
LDI
LDI
LDI
LDI
LDI
POP DE
JP PO,LFFDB
JR LFFD6
LFFD6: NOP
AND 0FFh
JR LFFBF
LFFDB: EX DE,HL
LD C,20h
ADD HL,BC
EX DE,HL
DEC A
JP NZ,LFFBC
LD SP,(LFF75)
POP AF
POP HL
POP DE
POP BC
EI
JP 0038h
LFFF0: NOP
NOP
NOP
NOP
DI
JP LFF79
Also,
https://www.youtube.com/watch?v=eGDLdf3nZL0 https://www.youtube.com/watch?v=wE1KylKQDrQ https://www.youtube.com/watch?v=79sg7UE6KAA https://www.youtube.com/watch?v=VB3mDqGgBag
should give you a good impression of what is possible.
HTH,
Volker
[1]
https://codersbucket.blogspot.com/2015/04/interrupts-on-zx-spectrum-what-are.html
[2]
http://www.zxdesign.info/interrupts.shtml
[3]
http://www.z80.info/zaks.html
--- SoupGate-Win32 v1.05
* Origin: fsxNet Usenet Gateway (21:1/5)