Path: csiph.com!fu-berlin.de!uni-berlin.de!individual.net!not-for-mail From: Volker Bartheld Newsgroups: comp.sys.sinclair Subject: Re: How did Treasure Island work? Date: Thu, 16 Jul 2020 12:30:12 +0200 Organization: bartheld.net Lines: 236 Message-ID: References: Mime-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit X-Trace: individual.net okRhqsK94j88WIfM7/fLggJsYjhvcou649eocd0AT85c/U1SwO Cancel-Lock: sha1:SwoKlBF3JArL5W1bPvRaGJ2Jg2w= User-Agent: 40tude_Dialog/2.0.15.41 Xref: csiph.com comp.sys.sinclair:4858 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