onspectrumcomputing.co.uk/forums/viewtopic.php?t=10714 WOOT 2023 there is a bunch off doublescreens off Clive Sinclair.
for best view you need a gigaviewer. that is a routine that mixes the 2 screens per scanline in realtime.
Work version 0147 is the one i used for the woot tape
Code: Select all
; giga screenflip per scanline
; gigaflipJR_147
; pasmo -d --tap --name gigaMC gigaflipJR_147.asm gigaflipJR_147.tap gigaflipJR_147.symbol
; pasmo -d --bin gigaflipJR_147.asm gigaflipJR_147.bin gigaflipJR_147.symbol
; cat gigaTAPE_bas.tap gigaflipJR_147.tap > gigaTAPEJR_147.tap
; you can use this giga viewer eg with
; https://github.com/KodeMunkie/imagetozxspec/releases
; General: Tape/slideshow >> CUSTOM and choose the latest gigaTAPE viewer !!!
; for slideshow compilation choose as 2nd and following screens an EMPTY TAPE
; just make an empty 0 byte txt file and rename it to 'empty.tap'
; Output >> tape/slideshow
; Preprocess: scaling >> 256x192
; Dither Colourmode >> gigascreen pallette (102)
; attribute >> favor most popular colours
;
; advanced serpentine OFF
; constrain to attribute OFF
; attr export order NONE
; colour distance CLASSIC
;
; of course you can experiment with any option you want, mind the amount of output !!!
; you WILL HAVE TO MANUALY RENAME EVERY MADE FILE
; ELSE !!
; IT WILL
; overwrite the last output, Img2ZXSpec.tap
; what a pitty if you work for half an hour to find A SINGLE FILE ONLY !!
; some test cases
; cat gigaTAPEJR_147.tap build/*.tap > gigaTAPE_SlideShow.tap
; cat gigaTAPEJR_147.tap clive/*.tap > CliveSinclair.tap
; cat gigaTAPEJR_147.tap Mozart_grey/*.tap > Mozart_grey.tap
; https://nos.nl/artikel/2467536-james-webb-telescoop-legt-zeldzaam-moment-ster-vast-kort-voor-supernova
; cat gigaTAPEJR_147.tap supernova/*.tap > supernova.tap
; + - + - + - +
; ! EPILEPTIC WARNING !
; + - + - + - +
; ! EPILEPTIC WARNING !
; + - + - + - +
; recommendation for emulators:
; https://retrovirtualmachine.org/download/
; not even that much eyestress
; set 'ORG here' value
here equ 32768+232 ;=33000 raising above 32768 makes the stack uncontended
calibrate equ 0 ; set 2 stripes in screen
counttime equ 0 ; count frames in 23672
switchbordercolour equ 0 ; switch bordercolour per frame for 25hz colours like orange or purple
keycheck equ 0 ; collect 2x 8+1 bytes of keyboard values
; RAM 7 is Screen and RAMDRIVE DIRECTORY, NO easy im2 trick allowed!!
; Editor uses addresses 60416, $EC00-$FFFF in physical RAM bank 7
; although >> $FD8C-$FF23 Not used. 408 bytes. ?jump to FDFD from FE00/FEFF
; $FF61-$FFFF Not used. 159 bytes. OR udg? 19*8=152,21*8=168
; jumptable MUST BE UNDER 49152-257, better lower basic?, channel area?, fixed adres anyway
; MIND STEADY TIMING IS ALWAYS NEEDED aswell within the last instruction of the momentary frame.
; best is to achieve time/4=x.0 , a 4fold step since thats the minimum time needed for any instruction.
; jr nz,there is 7 or 12
; ret nz is 5
; 7+5=12
; parts inside the interrupt are very timing vulnerable, although it looks rediculious, its needed
; jr nz,there;7 7+5jumping=12
; ret nz ;5 delay 7+5delay=12
;there ret ;10t > always 12+10t
; without you will see eg the calibration stripe reposition while pressing any key.
; for now i choose relative jumps for easy relocation. in bytesize JP nc 0x0000 vs JR nc 00, RET nc are equal in 3 bytes
; 'jr' takes 12t agains 'jp' needing 10t but for now relocation sets the standard above fastness
; timing will differ by use off the routine anyway, that coder decides jr vs jp
; AFTER succesfully creating or loading a picture in BOTH scr0 and scr1
; you can simulate the gigascreen with a screen flip per screenline
; start scr0 > scr1 > src0 > scr1
; the NEXT frame this must be done reversed
; start scr1 > src0 > scr1 > scr0
; 'its odd', an UNeven amount off SCANLINE switches will automate this FRAME difference
; http://www.worldofspectrum.net/faq/reference/128kreference.htm
; model -128k -timings in T-state
; T-state 228 per raster-scanline
; Scanline 311 per frame
; screen build in blocks with timing:
; hiddenlines 00000-03419t 000-014 15= 3420
; border-uppr 03420-14364t 015-063 48=10944
; screen 14365-58140t 064-255 192=43776
; border-down 58141-70907t 256-310 56=12768
; ---+----- ---+-----
; total 311=70908
; borderline = 38 * 228 = 8664
; borderline = 39 * 228 = 8892
; borderline = 40 * 228 = 9120
; borderline = 41 * 228 = 9348
; borderline = 42 * 228 = 9576
; borderline = 43 * 228 = 9804
; 1st screenline = 63 * 228 =14364
;first pix @16384 14364-1 t (zero-offset)
;A 128k-video screen line (228t) is timed as follows:
; 128 T ( 0-127) states of screen, (left to right ) CONtended
; 24 T (128-151) states of right border, (right to left !!!) UNcontended
; 48 T (152-199) states of horizontal retrace and UNcontended
; 28 T (200-227) states of left border. (4t extra on 224t ) UNcontended
; per scan line
; 0t 128t
; ----|+++ > +++|----151t
; |
; 199t - < - 152t
; |
; 200t 228t 356t
; ----|+++ > +++|----379t
; |
; 427t - < - 380t
; |
; 428t 456t
; ----|---->----|----
; screen time ( 0-127) = 128 tstate,
;right border time (128-151) = 24
; retracetime (152-199) = 48
; left border time (200-227) = 28 =128 24+48+28 = 228
; screen time (228-355) = 128
;right border time (356-379) = 24
; retrace time (380-427) = 48
; left border time (428-455) = 28 total 456 tstate
;https://www.worldofspectrum.net/faq/reference/z80reference.htm#Interrupts
;In IM 2, it takes 19 cycles to get to the interrupt routine:
; M1: 7 T states: acknowledge interrupt and decrement SP
; M2: 3 T states: write high byte and decrement SP
; M3: 3 T states: write low byte
; M4: 3 T states: read low byte from the interrupt vector
; M5: 3 T states: read high byte and jump to interrupt routine
; next t=+1 ULA interrupt does not wait for an instruction, so the instruction can be contended HALFWAY
; ut tstate average division
; ......
; 48k/128k+2 Cycle +2A/+3
; 6 14335 7 x/8=y.875 j.needle
;@16384 5 14336 6 x/8=y.00 64x224 null start !!
; 4 14337 5 x/8=y.125
; 3 14338 4 x/8=y.25
; *2 14339 3 x/8=y.375
; *1 14340 2 x/8=y.50
; *0 14341 1 x/8=y.625 <<<
; *0 14342 0 x/8=y.75 <<<
; 6 14343 7 x/8=y.875
; 5 14344 6 x/8=y.00
; 4 14345 5 x/8=y.125
; 3 14346 4 x/8=y.25
; 2 14347 3 x/8=y.375
; 1 14348 2 x/8=y.50
; 0 14349 1 x/8=y.625
; 0 14350 0 x/8=y.75
; 6 14351 7 x/8=y.875
; 5 14352 6 x/8=y.00
; 4 14353 5 x/8=y.125
; 3 14354 4 x/8=y.25
; 2 14355 3 x/8=y.375
; 1 14356 2 x/8=y.50
; 0 14357 1 x/8=y.625
; 0 14358 0 x/8=y.75
; 6 14359 7 x/8=y.875
; 5 14360 6 x/8=y.00
; 4 14361 5 x/8=y.125 j.needle
; 3 14362 4 x/8=y.25
; 2 14363 3 x/8=y.375
; 1@16384 14364 2 x/8=y.5 63×228 halve start !!
; 0 *14365 1 x/8=y.625
; 0 *14366 0_NO_delay x/8=y.75
; 6 *14367 7 x/8=y.875
;5<0+ 5 *14368 6 .0 >+6>6 <| check
;5<1+ 4 14369 5 .1 >+5>6 | apparent
;5<2+ 3 14370 4 .2 >+4>6 | number
;5<3+ 2 14371 3 .3 >+3>6 | cycle
;6<5+ 1 14372 2 .5 >+2>7 | in
;6<6+ 0 14373 1 .6 >+1>7 | Cycle
;6<7 0 14374 0_NOdelay .7 >+0>7 | +2A/+3
;14< 6 14375 7 .8 >+7>15 >>6 >| ONLY
; every (7th and) 8th cycle are 'UN'contended= NOT-delayed !!!!!!
; my own calc says:
; 19/8=2.375 8*0.375 x=3 > ut=+2
; 20/8=2.5 8*0.5 x=4 > ut=+1
; 21/8=2.625 8*0.625 x=5 > ut=+0
; 22/8=2.75 8*0.75 x=6 > ut=+0
; 19=10011 > 011 >> 100 = 4 -2= 2 ula
; 20=10100 > 100 >> 011 = 3 -2= 1 ula
; 21=10101 > 101 >> 010 = 2 -2= 0 ula
; 22=10110 > 110 >> 001 = 1 -2=-1 =0 ula
; sync idea IN a,(254)=11tstate and contended ?? 128k port 254 is UNcontended :)
; screentime bordertime
;@14364 14364+128=14492 +100 =14592 128-228
; +128=14720 +100 =14820 356-456 noncontention
;--== basic ==--
; 5 CLEAR VAL "32999": LET rt=SGN PI+PEEK VAL "23730"+VAL "256"*PEEK VAL "23731": PRINT "@";rt''TAB VAL "5"; BRIGHT SGN PI; FLASH SGN PI;"!"; FLASH NOT PI;" EPILEPTIC WARNING "; INVERSE SGN PI; FLASH SGN PI;"!"
; 7 PRINT ''"1, 2 change bordercolor"'"Q, W, E change screenflow"'"9, 0 change gigalines"''"B LOAD NEXT"'"SPACE CLS & LOAD NEXT"
; 10 LOAD "gigaMC"CODE rt
; 20 PRINT AT NOT PI,NOT PI;"LOADING SCREEN 0 ";AT NOT PI,NOT PI;: OUT VAL "32765",VAL "31": POKE VAL "23388",VAL "31"
; 23 FOR f=NOT PI TO VAL "18": POKE VAL "49152+6144+f",VAL "56": NEXT f: FOR f=NOT PI TO VAL "7": FOR g=NOT PI TO VAL "18": POKE VAL "49152+f*255+g",PEEK VAL "16384+f*255+g": NEXT g: NEXT f
; 27 LOAD "Loading..."CODE VAL "49152"
; 30 OUT VAL "32765",VAL "16": POKE VAL "23388",VAL "16": PRINT AT NOT PI,VAL "16";"1";AT NOT PI,NOT PI;: LOAD "Loading..."CODE VAL "16384"
; 40 RANDOMIZE USR (rt + PEEK rt)
; 45 GO TO VAL "20"
;--== _ _ _ ==--
;used sysvars, ports or just the adres used
attrp equ 23693
maskp equ 23694
ATTRT equ 23695
MASKT equ 23696
bordcr equ 23624 ; border colour
seed equ 23670
frames equ 23672 ; frame/time counter
mbank equ 23388 ; rambank configuration byte
ramPage equ 32765 ; port to set switch with
TSTACK EQU $5BFF ; Temporary stack (grows downwards). The byte at $5BFF is not actually used.
scr0 equ 16384 ; address SCREEN 0
scr1 equ 49152 ; address SCREEN 1
black equ 0
dblue equ 1
red equ 2
magneta equ 3
green equ 4
lblue equ 5
yellow equ 6
white equ 7
IF switchbordercolour
; for borderswitch set TWO colours here,
; 128+colour sets MSB value above contended memory for 'ld a,n OUT(254),a' instruction
borcolA equ 128+red
borcolB equ 128+yellow
ENDIF
; background definitions for later use
;paperA equ white
;paperB equ white
;inkA equ black
;inkB equ black
;bright_a equ 0
;bright_b equ 0
;flash_a equ 0
;flash_b equ 0
;--==--
; interupt address is set at BEGIN off file !!
; first start 'init' to build the interrupttable, needs 257 bytes space above routine
;
org here ; TRY (??) to keep it relocatable by avoiding hardcoded addresses
; sysvars are allowed hardcoded addresses/labels
defb init -intrstart +1 ; randomize usr (adres+peek adres) if smaller then 256 !!!!!!!!!
; 1 byte solution for ever changing entry adres
;---===--- interrupt SETS DI !!
tintrupt equ 19 +10 ; 19t to 22t a 4t syncbridge needed,1 halt is 4t x n
t0 equ tintrupt ; 10t for jump from 0xYyYy to intstart
intrstart: push af ; 11t
push bc ; 11t
push de ; 11t
push hl ; 11t
exx ; 4t
push af ; 11t
push bc ; 11t
push de ; 11t
push hl ; 11t common sysvar settings
exx ; 4t
push ix ; 15t
push iy ; 15t
Tintstart equ tintrupt +11+11+11+11 +4 +11+11+11+11 +4 +15+15
t1 equ Tintstart
t1bytes equ 14
IF counttime ; relocatable
time ld hl,(frames) ; 15t
inc hl ; 6t
ld (frames),hl ; 15t
ld a,l ; 4t
or h ; 4t
jr nz,del31 ; 7t >+5
ta equ 15+6+15+4+4+7
ret nz ;| 5t
ld hl,frames+2 ;| 10t
inc (hl) ;| 11t
jr tdone ;| 12t =38 max_time_count= 54 +38
tb equ 5+10+11+12
;} +5t jump on NZ
del31 ret z ;} 5t delay on NZ
ld a,(hl) ;} 7t delay
ld a,(hl) ;} 7t
ld a,(hl) ;} 7t
ld a,(hl) ;} 7t
tdone ; 5+5+7+7+7+7= 38t in '5freebytes' every 255 from 256 loops
Ttime equ ta+tb
t2b equ 23
ELSE
Ttime equ 0
t2b equ 0
ENDIF
t2 equ Ttime
t2bytes equ t2b
IF switchbordercolour ; MIND THE USE OF FRAME COUNTER = INTERRUPTS
swch ld a,(frames) ; 13t
rra ; 4t }=17 50frames/2
jr nc,mix2 ; 7t 50frames/2
ret nc ;| +5t delay
mix1 ld a,borcolA ;| 7t 'odd'
jr borderswch ;| 12t
;} +5t from jump
mix2 ld a,borcolB ;} 7t 'even'
jr borderswch ;} 12t STEADY JUMP is an DELAY
borderswch out (254),a ; 11t
Tborder equ 13 + 4 +7 + (5+ 7 +12) +11
t3b equ 17
ELSE
Tborder equ 0
t3b equ 0
ENDIF
t3 equ Tborder
t3bytes equ t3b
IF keycheck
testkey ld hl,keys ; 10t keys=hardcoded
ld bc,9 ; 10t
ld d,h ; 4t
ld e,l ; 4t
add hl,bc ; 11t
ex de,hl ; 4t
ldir ;} 21t 9*21-5 copy LASTKEYSET
tkeycopy equ 10+10+4+4+11+4+ (9*21) -5
ld hl,keys ; 10t
ld (hl),0 ; 7t
ld de,keys+1 ; 10t
ld bc,0xfefe ; 10t
; mind contended adress, but according fuse(160) this is all steady = same amount of tstate
ky in a,(c) ;\ 12t zeroflag only set if real 0, IN 254 is %10100000 or more so NZ flag is set
or %01000000 ;\ 7t patch 64 on 191 into 255
cpl ;\ 4t NO keys is ZERO now !!!
ld (de),a ;\ 7t store new keys
inc de ;\ 6t
or (hl) ;\ 7t collect any keys in 'keys'
ld (hl),a ;\ 7t
rlc b ;\ 8t rotate b into new portadres
jr c,ky ;\ 12t = 66
; -5t 10+7+10+10+8*(12+7+4+7+6+7+7+8+12)-5= 592 t
Tkeys equ tkeycopy + 10+7+10+10+ 8*(12+7+4+7+6 +7+7 +8+12)-5
t4b equ 36
ELSE
Tkeys equ 0
t4b equ 0
ENDIF
t4 equ Tkeys
t4bytes equ t4b
; calc needed delay UNTIL screentime
calcdelay equ 14364 -Tcdel - Tintstart - Ttime - Tborder - Tkeys - Tflap - Tcalib
Tcdel equ 10
ld bc,calcdelay ;10t
call BIGDELAY ; ~~bigdelay 17t+differ every time
t5 equ 10
t5bytes equ 6 ; actual routine is above 'initjump'
; the odd flip, change view TYPE here
delret ld bc,ramPage ;10t bc = 32765, port 0x7FFD
ld de,mbank ;10t de = 23388, sysvar
ld a,(de) ; 7t
flap xor %00001000 ; 7t flip SCR0 and SCR1 every frame
;and %11110111 ;.7t set SCR0 as start every frame
; or %00001000 ;.7t set SCR1 as start every frame
ld (de),a ; 7t
out (c),a ;12t port 0x7FFD
Tflap equ 10+10+7+7+7+12
t6 equ Tflap
t6bytes equ 12
IF calibrate
cali1 ld a,0 ;7 black
out (254),a ;11
ld a,7 ;7 white
out (254),a ;11 =36 in 8bytes
Tcalib equ 7+11+7+11
t7b equ 8
ELSE
Tcalib equ 0
t7b equ 0
ENDIF
t7 equ Tcalib
t7bytes equ t7b
;---===--- make screen switch/flip = OUT(c),a during bordertime = AFTER 1th 128 tstate screentime
lines equ 192
line ld l,lines ; 7t
lbytes equ 2
tlines equ 7
tot1 equ t0 + t1 + t2 + t3 + t4 + t5 + t6 + t7 + tlines ; hopefully 14364 tstate
; and under 255-1 bytes
jp1 ld c,9 ; 7t LOOP some screen time
dowaitc dec c ; 4t
jr nz,dowaitc ;12t
ret nz ; 5t sync12
tscrsync2 equ 7+ 9*(4+12)-5+5 +4+4; =159
flip ld bc,ramPage ;10t bc = 32765, port 0x7FFD
ld de,mbank ;10t de = 23388, sysvar
ld a,(de) ; 7t
flep xor %00001000 ; 7t flip screenbit
ld (de),a ; 7t horizontalretrace
out (c),a ;12t set SCR0/1 port 0x7FFD,result happens around 1/2 or 2/3 off the opcodetime
nop ; 4t
nop ; 4t
dec l ; 4t 14539
jr nz,jp1 ;12t 14551
;-5t
flipdone ret nz ; 5t sync delay
tflip equ 10+10 +7+7+7 +12 +4+12 ; =77
tloop equ tflip +tscrsync2 ; =228
tscreen equ lines * tloop -5 +5
tloopbytes equ 24
IF calibrate
cali2 ld a,0 ; 7t black
out (254),a ;11t
ld a,7 ; 7t white
out (254),a ;11t =36 in 8bytes
ENDIF
underbordertime ; mind the max frame time
pop iy ;14t
pop ix ;14t
exx ; 4t
pop hl ;10t common sysvar
pop de ;10t
pop bc ;10t
pop af ;10t
exx ; 4t
pop hl ;10t
pop de ;10t
pop bc ;10t
pop af ;10t
ret ;10t
tunderb equ 14+14+ 4+10+10+10+10+ 4+10+10+10+10 +10
tunderbytes equ 15
;-+-
tot2 equ tot1 + tscreen + Tcalib + tunderb
;-+-
;max total tstate =70908, do some nice in MAX 55 scanline = 55*228 = 12540 tstate
;amount off bytes before init is max 255 for "usr (adres+peek adres)" TRICK, can be dumped if needed
AA_totbyt equ t1bytes + t2bytes + t3bytes + t4bytes+ t5bytes + t6bytes + t7bytes + lbytes +tloopbytes +tunderbytes
init LD A,(0x0B52) ;13t ROM adres 2898 holds
CP 214 ; 7t 214=48k 195=128k
ret Z ; 5t quit if 48k or 16k
di ; 4t
exx ; 4t alt
push hl ;11t save common sysvars setting(s)
exx ; 4t back to BC=USR adres
writetable ld hl,codelength ;10t length this routine
add hl,bc ;11t BC is usr adres
inc h ; 4t align 256 ABOVE this routine
ld l,0 ; 7t ,, ,,
ld d,h ; 4t
ld e,1 ; 7t
ld a,h ; 4t
ld i,a ; 9t table @0xhh00
inc a ; 4t jump adres will be 0x(h+1)(h+1)
ld (hl),a ; 7t
ld bc,256 ;10t
ldir ; 24-5 = (256*24)-5
;hl=0x8400
ld de,here+1 ;10t
ld l,h ; 4t hl=0xYyYy
ld (hl),195 ; 7t 0xc3= JP
inc hl ; 6t
ld (hl),e ; 7t jpLSB
inc hl ; 6t
ld (hl),d ; 7t jpMSB
pop hl ; restore sysvar settings (errnr) for EI and Basic
exx ; and move it to the alternate registers
im 2 ; 8t i_reg already set
doeint ei ; 4t
nop ; 4t still part of old_frame!! every tstate counts up
halt ; 4 * ~~t and now just wait and watch
tst0 ;;; interrupt and back
;;; ~~12768 tstate left after last screen scanline
keyed ld a,0x7F ; 7t
in a,(0xFE) ;11t only reached if total Tstate is less then 1 FRAME=70908-57
bit 4,a ; 8t
jr z,ReturnToBASIC ; 7+5t
ret z ; 5t delay
bit 0,a ; 8t space key
jr z,cls ; 7+5t
ret z ; 5t delay
jr doeint ;12t
thalt equ 4+4+4 +7+11 +8+7+5 +8+7+5 +12 ;=82
;-+-=-+-=_=-+-=-+-_-+-=-+-=_=-+-=-+-_-+-=-+-=_=-+-=-+-_-+-=-+-=_=-+-=-+-
;-+-=-+-=_=-+-=-+-_-+-=-+-=_=-+-=-+-_-+-=-+-=_=-+-=-+-_-+-=-+-=_=-+-=-+-
IF keycheck
keys defs 18,0
ENDIF
;page defb 0
;https://github.com/ZXSpectrumVault/rom-disassemblies/blob/master/Spectrum%20128K/Spectrum128_ROM0.asm
; this is outside the interrupt routine so timing aint importend anymore,
; it will continue after IM2 asifnothing happend ;-) will it ???
; yet UNEVEN timing will show, x/4=y.0 !! best approach
; without keybank direct test is needed
; Cs+ z+ x+ c+ v keys +1 0xFE
; a+ s+ d+ f+ g keys +2 0xFD
; q+ w+ e+ r+ t keys +3 0xFB
; 1+ 2+ 3+ 4+ 5 keys +4 0xF7
;--0--1--2--3--4--bitposition
; 0+ 9+ 8+ 7+ 6 keys +5 0xEF
; p+ o+ i+ u+ y keys +6 0xDF
; En+ l+ k+ j+ h keys +7 0xBF
; Sp+Ss+ m+ n+ b keys +8 0x7F
;-+-=-+-=_=-+-=-+-_-+
setpage0 ld hl,0xF000 ;10t h=11110000 l=00000000
jr setpage ;12t
setpage7 ld hl,0xF007 ;10t h=11110000 l=00000111
setpage ld bc,ramPage ;10t bc = 32765, port 0x7FFD
ld de,mbank ;10t de = 23388, sysvar
LD A,R ; 9t P/V flag=Interrupt status (Toni Baker et all)
PUSH AF ;11t Stack interrupt status.
ld a,(de) ; 7t
and h ; 4t set rambank 0 SCREEN 0
or l ; 4t set rambank 7
ld (de),a ; 7t
out (c),a ;12t port 0x7FFD
POP de ;10t P/V flag=Former interrupt status. (Toni Baker et all)
bit 2,e ; 8t FLAGregister = %SZ-H-PNC po/pe =bit2
; https://learn.cemetech.net/index.php/Z80:Flags_and_Bit-Level_Instructions#F_Register
; https://clrhome.org/table/#jp
; JP PO,NONEI ;10t Jump if interrupts were previously disabled.
jr nz,NONEI ; 7+5t
EI ; 4t Re-enable interrupts.
NONEI: ;
ret ;10t
tpage equ 10+10 +9+11 +7+4+4+7 +12+10+8 +(12 ) +10 ;=114
tpagei equ 10+10 +9+11 +7+4+4+7 +12+10+8 +(7+4) +10 ;=113
tsetp0 equ 10+12+tpage ;=136
tsetp7 equ 10+tpage ;=124
;-+-=-+-=_=-+-=-+-_-+
; Paradigm Shifter's fast CLS
; rewritten to Fast Double CLS
; LDIR = 24tstate for 1 byte
; push = 11tstate for 2 bytes = 5.5 tstate per byte
; A -> attrib to set when clearing screen
; use the ATTRT sysvar and the MASKT sysvar as attribute for BOTH screens
; data needs better place
;attr_a defb 56 ; data adres hardcoded
; defb 56
cls di ; 4t disable interrupt
; ld hl,back1 ; 10t hardcoded ADRES
; push hl ; 11t
call setpage7 ;17+74t for this jump
ld hl,16384 +6144 +768 ;+2
; 10t start address top off attribute area +2 since stack lowers 2 and then sets value ld a,(ATTRT) ; 13t scr0 attr
ex af,af' ; 4t
ld a,(MASKT) ; 13t scr1 attr
tcls1 equ 4+ 17+74 +10 +13+4+13
hlset ex af,af' ;| 4t
; push hl ;| 11t store value BEFORE changes to SP
; ld (seed),sp ;| 20t store current stack pointer, using a free sysvar is relocatable
ld sp,hl ;| 6t
ld bc,0x2002 ;| 10t c=2 rounds, b=32 and b=0=256
hala ld d,a ;|\ 4t 1st set attribute in b=32 * 12 pushes
ld e,a ;|\ 4t 2nd set screen in b=256 * 12 pushes
stackloop push de ;|\]11t
push de ;|\]11t
push de ;|\]11t
push de ;|\]11t
push de ;|\]11t
push de ;|\]11t
push de ;|\]11t
push de ;|\]11t
push de ;|\]11t
push de ;|\]11t
push de ;|\]11t
push de ;|\]11t
djnz stackloop ;|\]13t 32*12=384 pushes off 2 bytes = 768 bytes
tcls2 equ 4+11+20 +6+7+4+4 +32*((11*12)+13) -5 ;= 4691t
ld a,b ;|\ 4t
dec c ;|\ 4t
jr nz,hala ;|\ 12t
;| -5t
; ld sp,(seed) ;| 20t fetch old StackPointer
; pop hl ;| 10t
bit 7,h ;| 8t
jr nz,ReturnToBASIC ;| 7t+5 jump will set page0
set 7,h ; 8t
jr hlset ; 12t
tcls3 equ 4+4+4+4 + 256*((11*12)+13) -5 +20 +10+8+7
tcls4 equ 8+12
tcls equ tcls1 + tcls2+tcls3 + tcls4 + tcls2+tcls3 +5
;pasmo=16bit >~~18358+65536=~~83894 tstate for a DOUBLE CLS, just 12986t above 70908,a single frame !!
; but in DI time !!, now slize it in perhaps blocks off ~~12000 tstate
;-+-=-+-=_=-+-=-+-_-+
ReturnToBASIC: ; after closing interrupt timing is back to normal chaos
ld a,(bordcr) ;13t
out (254),a ;11t
swoff di ; 4t @ OFF
; ld hl,back2 ; 10t
; push hl ; 11t
call setpage0 ;17t +
LD A,$3F ; 7t
LD I,A ; 9t
_im_1 IM 1 ; 8t Interrupts OFF cq normal
ei ; 4t no more tstate counting needed for now
nop ; 4t spare space for a ret
; finally assume 128k mode is wanted and switch to it
; an old switch 128 to 48k routine by Cecil Westerhoff 1988,
; from “Impuls” this routine helps switching between 48k
; and 128k mode without losing any software
; mode_128 entry (48k>>128kmode)
m128 LD HL,0x5B1D ; $5B1D = MAIN_4 ( 128 )
LD DE,0x1821 ; $1821 = STMT_RET ( 128 )
LD B,0x10 ; 128k-mode
JR mc ;
;mode_48 entry (128k>>48kmode)
m48 LD HL,0x1303 ; $1303 = MAIN_4
LD DE,0x1B76 ; $1B76 = STMT_RET
LD B,0 ; 48k-mode
mc DI ; 4t
LD SP,(0x5C3D) ; empty stack
EX (SP),HL ; put ret-address on stack
PUSH DE ; put ret-address on stack
LD A,(0x5C3B) ; flag for mode
AND 0xEF ; reset bit 4
OR B ; signal which mode
LD (0x5C3B),A ; save flag for mode
LD A,0x10 ; \
XOR B ; switch bit 4 van B
LD B,A ; /
LD A,(mbank) ; get bank_M
AND 0xEF ; reset bit 4
OR B ; signal which rom
LD (mbank),A ; save bank_M
LD BC,ramPage ; output-port bankswitching
OUT (C),A ; output
RET ; exit mode switch to basic MAIN_4
;max total tstate =70908, do some nice in MAX 55 scanline = 55*228 = 12540 tstate
;-+-=-+-=_=-+-=-+-_-+
; https://worldofspectrum.org/forums/discussion/comment/214851/#Comment_214851
; Z80 delay routine, but must be UNcontended !!!!!
; by Jan Bobrowski, license GPL
; wait bc T (including call; bc>=141)
; destroys: af, bc, hl
BIGDELAY:
ld hl,-141 ; 10t duration this routine
bigdel2 add hl,bc ; 15t bc= desired delay
ld bc,-23 ; 10t
loop add hl,bc ;|15t is hl-23
jr c,loop ;|10t
ld a,l ; 4t
add a,15 ; 7t
jr nc,g0 ; 7+5
cp 8 ; 7t
jr c,g1 ; 7+5
or 0 ; 7t strikes CARRY
g0 inc hl ; 6t
g1 rra ; 4t
jr c,b0 ; 7+5
nop ; 4t
b0 rra ; 4t
jr nc,b1 ; 7+5
or 0 ; 7t
b1 rra ; 4t
ret nc ; 5+6
ret ; 10t ret = 10t DELAY ASWELL and not to be removed for 'smart replacement'
codelength equ the - here
the end ; here
; change screen flow instructions
key3 ld hl,flap
bit 0,a
jr nz,flop0 ;>30t
ret nz ; delay ;=30t
bit 1,a
jr nz,flop1 ;>50t
ret nz ; delay ;=50t
bit 2,a
jr nz,flop2 ;>70
ret nz ;=70 delay, not needed
ret ;=80t while return without checking last 2 bits
; then its a delay of 80t from 70908 t
; change start between scr0 and scr1
flop0 ex af,af'
bit 0,a
ret nz ; key was pressed already
ex af,af' ; needed?
ld a,0xee ; 'XOR' data
ld (hl),a
inc hl
ld a,%00001000 ; data=8
ld (hl),a
ret
; start with scr0
flop1 ex af,af'
bit 1,a
ret nz ; key was pressed already
ex af,af' ; needed?
ld a,0xe6 ; 'AND' data
ld (hl),a
inc hl
ld a,%11110111 ; data=247 , ~8
ld (hl),a
ret
; start with scr1
flop2 ex af,af'
bit 2,a
ret nz ; key was pressed already
ex af,af' ; needed?
ld a,0xf6 ; 'OR' data
ld (hl),a
inc hl
ld a,%00001000 ; data=8
ld (hl),a
ret
key4 ; set label
IF switchbordercolour
bit 0,a
jr nz,mx1
ret nz ; delay
bit 1,a
jr nz,mx2
ret nz ; delay
ret
mx1 ex af,af'
bit 0,a
ret nz ; key was pressed already
ex af,af' ; needed?
ld a,(mix1+1)
inc a
and 7
ld (mix1+1),a
ret
mx2 ex af,af'
bit 1,a
ret nz ; key was pressed already
ex af,af' ; needed?
ld a,(mix2+1)
inc a
and 7
ld (mix2+1),a
ENDIF
ret ; set RET always
key6c jr key6
key7c jr key7
key8c jr key8
; set amount of switched lines, counted topdown
key5 ld hl,line+1
bit 0,a
jr nz,lineup
ret nz ; delay
bit 1,a
jr nz,linedown
ret nz ; delay
ret
lineup ex af,af'
bit 0,a
ret nz ; key was pressed already
ex af,af' ; needed?
ld a,192
cp (hl)
ret z
inc (hl)
ret
linedown ex af,af'
bit 1,a
ret nz ; key was pressed already
ex af,af' ; needed?
ld a,1 ; there is always a scanline , believe me !!!
cp (hl)
ret z
dec (hl)
ret
key6 ret
key7 ret
key8 bit 0,a ; 8t space key ??
jr nz,cls ;12t
bit 4,a
jr nz,ReturnToBASIC
ret ;10t