gigaviewer

Share graphical tips, notes and queries related to our favourite screen layout and its editors.
Post Reply
C.Born
Manic Miner
Posts: 229
Joined: Sat Dec 09, 2017 4:09 pm

gigaviewer

Post by C.Born »

Hello
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

C.Born
Manic Miner
Posts: 229
Joined: Sat Dec 09, 2017 4:09 pm

Re: gigaviewer

Post by C.Born »

meanwhile i re-introduced some module parts and i try to make a standard calculation for the delay routine
keys SHift and Z will change the WAIT cyclus with 1tstate per key press IF you set "calibration" to 1
finaly the included keycheck should do that aswell
hopefully one day its all self calculating and using IX to maintain relocatability

Code: Select all

; giga screenflip per scanline

; gigarotJR_0177b
; pasmo -d --tap --name gigaMC gigarotJR_0177b.asm gigarotJR_0177b.tap gigarotJR_0177b.symbol
; pasmo -d --bin gigarotJR_0177b.asm gigarotJR_0177b.bin gigarotJR_0177b.symbol

; cat gigaTAPE_bas+2.tap gigarotJR_0177b.tap > gigaROTEJR_0177b.tap
; cp  gigaROTEJR_0177b.tap ~/gigaROTEJR_0177b.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'
;                                  and select it with 'CUSTOM'
;              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_0177b.tap build/*.tap       > gigaTAPE_SlideShow_0177b.tap
; cat gigaTAPEJR_0177b.tap clive/*.tap       > CliveSinclair_0177b.tap
; cat gigaTAPEJR_0177b.tap Mozart_grey/*.tap > Mozart_grey_0177b.tap

; https://nos.nl/artikel/2467536-james-webb-telescoop-legt-zeldzaam-moment-ster-vast-kort-voor-supernova
; cat gigaTAPEJR_0177b.tap supernova/*.tap   > supernova_0177b.tap


; +  -  +   -   +  -  +
; ! EPILEPTIC WARNING !
; +  -  +   -   +  -  +
; ! EPILEPTIC WARNING !
; +  -  +   -   +  -  +

; recommendation for emulators:
; https://retrovirtualmachine.org/download/
; not even that much eyestress


; set 'ORG here' value

here       equ 32768+732  ;=33500 raising above 32768 makes the stack uncontended
                             ;0 = none
calibrate             equ 1  ;1 =ok set 2 stripes in screen
counttime             equ 0  ;2 =ok count frames in 23672
switchbordercolour    equ 0  ;3 =ok switch bordercolour per frame for 25hz colours like orange or purple
keycheck              equ 1  ;4 =ok collect 2x 8+1 bytes of keyboard values (only the check, the USE can be everywere/when)
rotatescreen          equ 0  ; not    ATTEMPT to horizontal rotate the whole double screen bit by bit


; 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 ridiculous, 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-under 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 ==--
;   1 DEF FN a(a)=PEEK a+256*PEEK (a+SGN PI): DEF FN c(i,p,b,f) =VAL "i+8*p+64*b+128*f"
;   2 DEF FN c$(i,p,b,f)=CHR$ 16+CHR$ i+CHR$ 17+CHR$ p+CHR$ 19+CHR$ b+CHR$ 18+CHR$ f
;   5 DATA "",NOT PI,NOT n,n,VAL "7",i1,n,e,n,n,n,FN c$(i0,p0,b0,f0)
;  10 CLEAR VAL "33499": LET rt=FN a(VAL "23730")+SGN PI: PRINT "GigaViewer @";rt'"Toastrack only"
;  30 READ s$,n,e,i0,i1,p0,p1,b0,b1,f0,f1,e$
;  50 PRINT '"SPACE    CLS & LOAD NEXT"''"F0:";f0,"F1:";f1,"B0:";b0,"B1:";b1,"P0:";p0,"P1:";p1,"I0:";i0,"I1:";i1
;  70 LET a0=FN c(i0,p0,b0,f0): LET a1=FN c(i1,p1,b1,f1): LET c$=FN c$(n,7,n,n)
;  80 PRINT '"set attributes:"'"SCR0 in ATTRT 23693,";a0;FN c$(i0,p0,b0,f0);TAB 31;"+"'c$;"SCR1 in MASKT 23694,";a1;FN c$(i1,p1,b1,f1);TAB 31;"+"
;  90 PRINT AT 18,0;"emulators recommendation:"'"RetroVirtualMachine","SPIN"'"RealSpectrum rs32"'"ZXesaruX SDL1.2"
; 100 PRINT AT VAL "21",VAL "5"; BRIGHT SGN PI; FLASH SGN PI;"!"; FLASH n ;" EPILEPTIC WARNING "; INVERSE SGN PI; FLASH SGN PI;"!";AT VAL "11",NOT PI;
; 110 LOAD "gigaMC"CODE rt
; 120 IF s$="" THEN  GO TO 190
; 130 POKE VAL "23693",a0: POKE VAL "23694",a1
; 140 PRINT AT NOT PI,NOT PI;"SCR1  ";: OUT VAL "32765",VAL "31": POKE VAL "23388",VAL "31"
; 150 FOR f=NOT PI TO INT PI: POKE VAL "49152+6144+f",VAL "56": NEXT f
; 160 FOR f=SGN PI TO VAL "6": FOR g=NOT PI TO VAL "3": POKE VAL "49152+f*256+g",PEEK VAL "16384+f*256+g": NEXT g: NEXT f
; 170 PRINT AT VAL "11",NOT PI;: LOAD s$CODE VAL "49152"
; 180 OUT VAL "32765",VAL "16": POKE VAL "23388",VAL "16": PRINT AT NOT PI,INT PI;"0";AT VAL "12",NOT PI;: LOAD s$CODE VAL "16384"
; 190 LET bc=USR rt: PRINT 'bc: FOR f=0 TO 100: NEXT f
; 200 GO TO VAL "100"
; 210 CLEAR : SAVE "giga+" LINE SGN PI
;--== _ _ _ ==--


;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




; 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
                                           ; if you know a STEADY timed ROM just try it!!

startstep  equ init - here

                  ld hl,startstep
                  add hl,bc               ; start adres
                  jp (hl)                 ; jp (hl) is not a pointer but THE adres !!!
                                          ; WHY is this the ONLY different and REVERSED notification?
                                          ; it should be JP HL only since thats what is DOES
; small data block 
;       set IX if ALL is introduced

;page defb 0

lines           defb 192   ; amount off lines to flip


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         defb 128+red
borcolB         defb 128+yellow
ENDIF


IF rotatescreen
adrlines        defw 0x4000
rotlines        defw 0x0808

rcolour         defw 0x5800
atrlines        defb 0x18

rups            defb %00001000      ; count middle pixel for colour rotate
                                    ; set 0 for faster B/W ???????????????
ENDIF   ; end rotate variables

IF keycheck 
keys            defs 18,0
ENDIF


;---===---   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   ;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
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)       ;| 13t  'odd'
                  jr borderswch        ;| 12t

                                       ;} +5t from jump
mix2              ld a,(borcolB)       ;} 13t  'even'
                  jr borderswch        ;} 12t  STEADY JUMP is an DELAY

borderswch        out (254),a          ;  11t

Tborder           equ 13 + 4 +7 + (5+ 13 +12) +11
t3b               equ 19
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
; in 128k port 254 is NOT contended
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 10+10+4+4+11+4+ (9*21) -5 + 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



IF rotatescreen    ;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

rotate          ld de,(rotlines)    ;20t
setline         ld hl,(adrlines)    ;16t SCR0  hl=16384
                call setra          ;17t b=32     d=8 e=8
                                    ;    a=scr0 , a'=scr1

rota0           rra                 ; 4t set scr0 start bit %7654321c >c
                ex af,af'           ; 4t go scr1
                rra                 ; 4t set scr1 start bit %7654321c >c
tsetln   equ 20+16+17 +tsetra +4+4+4


rota_b          ex af,af'           ; 4t back to scr0
                res 7,h             ; 8t go scr0
                rr (hl)             ;15t rotate scr0 a single bit

                ex af,af'           ; 4t go scr1
                set 7,h             ; 8t go scr1
                rr (hl)             ;15t rotate scr1 a single bit

                inc l               ; 4t
                djnz rota_b         ;13t rotate 32 bytes on 2 screens AT once
                                    ;-5t
trotab equ 32*(4+8+15+4+8+15+4+13)-5

                ld hl,adrlines+1    ;10t
                inc (hl)            ; 7t
                dec e               ; 4t
                jr nz,dd0           ; 7t
                ret nz              ; 5t delay
deb0 equ 10+7+4+7+5

                ld e,8              ; 7t set counter
                ld a,(hl)           ; 7t
                sub e               ; 4t
                ld (hl),a           ; 7t

                dec hl              ; 6t adrlines
                ld a,0x20           ; 7t
                add a,(hl)          ; 7t
                ld (hl),a           ; 7t

                ;push de 
                push hl              ;11t
                ;ld (adrlines),hl

checkbit4       ld a,(rups)         ;13t all bits done, attr once in 8 times on CARRY
                bit 0,a             ; 8t
                jr z,delong         ; 7+5
                ret z               ; 5t delay
tsetcount   equ 7+7+4+7 +6+7+7+7 +11 +13+8+7+5
deb1        equ tsetcount


coladr          ld hl,(rcolour)     ;16t
nattr           call setra          ;17t +jmp
tnattr      equ 16+17+tsetra

col1            ld c,(hl)           ; 7t
                ld (hl),a           ; 7t
                ld a,c              ; 4t
                ex af,af'           ; 4t
                set 7,h             ; 8t
                ld c,(hl)           ; 7t
                ld (hl),a           ; 7t
                ld a,c              ; 4t
                ex af,af'           ; 4t
                res 7,h             ; 8t
                inc hl              ; 6t
                djnz col1           ;13t  32*(7+7+4+4+8 +7+7+4+4+8 +6+13)-5  =2523
                                    ;-5t
tcol1       equ 32*(7+7+4+4+8 +7+7+4+4+8 +6+13)-5

                ld hl,(rcolour)     ;16t
                ld bc,0x20          ;10t
                add hl,bc           ;15t
                ld (rcolour),hl     ;16t

                ld hl,atrlines      ;10t
                dec (hl)            ; 7t
                jr nz,delcol        ; 7t
                ret nz              ; 5t
traisecol   equ 16+10+15+16 +10+7 +7+5

                ld (hl),0x18        ;}10t  atrlines reset 24 lines
                ld hl,0x5800        ;}10t
                ld (rcolour),hl     ;}16t
                jr nextd            ;}12t
tsetcol     equ 10+10+16+12   ;=48

tatter      equ tnattr  + tcol1  + traisecol + tsetcol
tatr24      equ tatter*24

delcol          jr dlc1             ;|12t delay
dlc1            jr dlc2             ;|12t
dlc2            jr dlc3             ;|12t
dlc3            jr nextd            ;|12t  =48t

tat7    equ tatter-7
tt73        equ tat7/13
tt73a       equ tt73*13
tt73r       equ tat7-tt73a

tt74        equ tat7/14
tt74a       equ tt74*14
tt74r       equ tat7-tt74a

tt76        equ tat7/16
tt76a       equ tt76*16
tt76r       equ tat7-tt76a


delong          ld b,tt73           ;{ 7t
dlg             djnz dlg            ;{ 7+10*13-5=132
                ret nz              ;{ 5t still Z set from 'jr z,delong'
tdelong equ  7+ (tt73*13)-5 +5


nextd           ;ld hl,(adrlines)
                pop hl              ;10t
                ;pop de

                dec d               ; 4t
                jr nz,dd1           ; 7t
                ret nz              ; 5t delay
deb2 equ 10 +4+7+5

docounter       ld d,8              ; 7t set counter
                inc hl              ; 6t adrlines+1
                ld a,d              ; 4t
                add a,(hl)          ; 7t
                ld (hl),a           ; 7t

                cp 0x58             ; 7t
                jr c,dd2            ; 7t
                ret c               ; 5t delay
deb3 equ 7+6 +4+7+7 +7+7+5

                ld (hl),0x40        ;10t
                ld (rotlines),de    ;20t

                ld hl,rups          ;10t
                rrc (hl)            ;15t rotate COLOUR CARRY, attr once in 8 times on CARRY
                jr joveret         ;12t

deb4 equ 10+20+10+15 +12







dd0             ret z               ; 5t from JR NZ , no ret  
                ld a,(hl)           ; 7t DELAY
                ld a,(hl)           ; 7t DELAY
                ld a,(hl)           ; 7t DELAY
                
dd1             res 0,a             ; 8t DELAY
                ld a,(hl)           ; 7t DELAY
                ld a,(hl)           ; 7t DELAY
                ld a,(hl)           ; 7t DELAY
                ld a,(hl)           ; 7t DELAY
                ld a,(hl)           ; 7t DELAY 
                ld a,(hl)           ; 7t DELAY 8 + 7*6 =50

dd2             ld a,(hl)           ; 7t DELAY
                ld a,(hl)           ; 7t DELAY
                ld a,(hl)           ; 7t DELAY
                ld a,(hl)           ; 7t DELAY
                ld a,(hl)           ; 7t DELAY
                ld a,(hl)           ; 7t DELAY
                ld a,(hl)           ; 7t DELAY
                ld a,(hl)           ; 7t DELAY
                ld a,(hl)           ; 7t DELAY
                nop                 ; 4t delay  9*7 + 4 =67

                jr joveret         ;12 last RET of routine

bub1        equ deb1
bub2        equ deb1+deb2           ; EQU 0001AH  ; 26
bub3        equ deb1+deb2+deb3      ; EQU 0004CH  ; 76
bub4        equ deb1+deb2+deb3+deb4 ; EQU 0008FH  ; 143
		
dubdel0     equ bub4                ;
dubdel1     equ bub4-bub1           
dubdel2     equ bub4-bub2           ;
dubdel3     equ bub4-bub3           ;


setra           ld bc,31            ;10t
                add hl,bc           ;11t end of pixel line

                ex af,af'           ; 4t scr1
                set 7,h             ; 8t SCR1  49152
                ld a,(hl)           ; 7t last byte first line scr1

                ex af,af'           ; 4t go scr0
                res 7,h             ; 8t go scr0
                ld a,(hl)           ; 7t last byte first line scr0

                and a               ; 4t reset flags
                sbc hl,bc           ;15t back to 16384

                ld b,32             ; 7t
                ret                 ;10t

tsetra      equ 10+11 +4+8+7 +4+8+7 +4+15 +7+10
joveret     equ $

;time for 1 frame cq line rotation
Trotatescr  equ tsetln + trotab + bub4 + tdelong  ; what did i do to much here, since i did
ELSE
Trotatescr  equ 0
ENDIF
t5a equ Trotatescr


;-=-=-=-=-=-=-=-=-=-=-=-=
; calc needed delay UNTIL screentime
Tearlystart equ     0   ; change timing a bit
T0calcdelay equ Tintstart + Ttime + Tborder + Tkeys + Trotatescr + Tcdel + Tflap + Tcalib + Tearlystart

                jr setcalc       ;
bigbel          defw 0 - Tintstart - Ttime - Tborder - Tkeys - Trotatescr - Tcdel - Tflap - Tcalib - Tearlystart

setcalc         ld de,14364
                ld hl,(bigbel)   ;16t a negative number !?!?
                add hl,de
                ld b,h
                ld c,l
                call bigdelay    ; ~~bigdelay  17t+differ every time

Tcdel       equ 10            ; calling time included in bigdelay
t5bytes     equ 6             ; actual routine is above 'initjump'
t5          equ Tcdel

; 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/1  start 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 , contended

Tflap   equ 10+10+7+7+7+12
t6      equ Tflap
t6bytes equ 12

IF calibrate    ;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

calkey            ld hl,(bigbel)  ;    16
                  ld a,254           ;     7 key row 1, SHzxcv
                  in a,(254)         ;    11

                  bit 0,a            ;     8
                  jr nz,bit0d        ;     7
                  ret nz             ;     5

                  dec hl             ; }   6
                  jr dobit1          ; }  12 =6+12=18

bit0d             ld b,(hl)          ;|    7
                  ld b,(hl)          ;|    7
                  nop                ;|    4=7+7+4=18

dobit1            bit 1,a            ;     8
                  jr nz,bit1d        ;     7
                  ret nz             ;     5

                  inc hl             ; ]   6
                  jr writenewcalc    ; ]  12

bit1d             ld b,(hl)          ;     7
                  ld b,(hl)          ;     7
                  nop                ;     4=7+7+4=18

writenewcalc      ld (bigbel),hl  ;|}] 16

cali1           ld a,128+0         ;7   black
                out (254),a    ;11
                ld a,128+7         ;7   white
                out (254),a    ;11  =36 in 8bytes
Tcalib  equ 7+11 +16+8+7  +5+8+7+ 5+16 +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

line            ld a,(lines)          ;13t
                ld l,a                ; 4t
lbytes equ 4
tlines equ 13 + 4

Tot1   equ T0calcdelay + t1 + t2 + t3 + t4 + t5a + t5 + t6 + t7  + tlines    ; hopefully 14364 tstate (14381 ??)


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  ; =151

flep            ld  bc,ramPage        ;10t bc = 32765, port 0x7FFD, contended adres
                ld  de,mbank          ;10t de = 23388, sysvar
                ld  a,(de)            ; 7t
flip            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+4 +4+12 -5 +5 ; =77

tloop             equ tflip +tscrsync2  ;  =228
tscreen           equ lines * tloop -5 +5
tloopbytes equ 24

IF calibrate
cali2             ld a,128+0                ; 7t black
                  out (254),a           ;11t
                  ld a,128+7                ; 7t white
                  out (254),a           ;11t =36 in 8bytes
ENDIF


;                ;------------------------
underbordertime  ; mind the max frame time underborder 12540
;                ;------------------------


                  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,intrstart          ;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

; outside interrupts
inkeys          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

;-+-=-+-=_=-+-=-+-_-+-=-+-=_=-+-=-+-_-+-=-+-=_=-+-=-+-_-+-=-+-=_=-+-=-+-


;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=11111000 l=00000000
                jr setpage       ;12t

setpage7        ld hl,0xF007     ;10t h=11111000 l=00000111
                jr setpage       ;12t delay

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.

                di               ; 4t
                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      ;  7t
                ret nz           ;  5t delay
 
                EI               ;} 4t Re-enable interrupts.
                jr doei          ;} 12t

                                 ;] +5 jump
NONEI:          nop              ;] 4t    
                jr doei          ;]12t

doei            ret              ; 10t

tpage   equ 10+10 +9+11 +4 +7+4+4+7 +12+10+8 +(7+5) +(4+12) +10  ;=134

tsetp   equ 10+12+tpage          ;=152


;-+-=-+-=_=-+-=-+-_-+
; 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


cls               di                  ;    4t disable interrupt
;                  ld hl,back1         ;   10t  hardcoded ADRES
;                  push hl             ;   11t
                  call setpage7       ;   17+tpage for this jump

                  ld hl,23296         ;   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+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 +8+7+5
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 !!


;-+-=-+-=_=-+-=-+-_-+
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 + tpage
                  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

                  ld bc,(bigbel)    ;20t
doret             RET               ;10t exit

;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=hl-141 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'


key8              bit 0,a          ; 8t space key ?? 
                  jr nz,cls        ;12t
                  bit 4,a
                  jr nz,ReturnToBASIC
                  ret              ;10t


key1

; 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



codelength equ the - here
the  end ;  here

User avatar
Jbizzel
Dynamite Dan
Posts: 1537
Joined: Mon May 04, 2020 4:34 pm
Location: Hull
Contact:

Re: gigaviewer

Post by Jbizzel »

Thank you for sharing this - I've been wondering about it since you WOOT submission.

This is the code from the basic generated by imagetozxspec. Is this all that is needed for a simple viewer? Ran in USR0 mode.

Code: Select all

370 CLEAR 49151
380 POKE 23739,111 
390 OUT 32765,21 
400 LOAD "" CODE 49152 
410 OUT 32765,23 
420 LOAD "" CODE 49152 
430 PAUSE 1 
440 OUT 32765,16 
450 PAUSE 1 
460 OUT 32765,24
470 IF INKEY$<>"" THEN GO TO 370
480 GO TO 430
Of course I dont understand it LOL. Is "390 OUT 32765,21" etc changing the paged memory, then 440/460 changing the page that is the screen memory? IDK

I made a gigascreen image..

This is on real hardware. It just blows my tiny mind that this is possible.

Image
C.Born
Manic Miner
Posts: 229
Joined: Sat Dec 09, 2017 4:09 pm

Re: gigaviewer

Post by C.Born »

Hi
well, not for above gigaviewer ASM file , then you first have to compile the basic and of course the asm

Code: Select all

   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"
I use Pasmo for the asm
https://pasmo.speccy.org/
; pasmo -d --tap --name gigaMC gigaflipJR_147.asm gigaflipJR_147.tap gigaflipJR_147.symbol

and emu2txt for the basic
www.users.globalnet.co.uk/~jg27paw4/pourri/txt2emu.zip

and stick them togehter with
cat gigaTAPE_bas.tap gigaflipJR_147.tap > gigaTAPEJR_147.tap

then inside img2spectrum in the settings menu choose "custum" and the the by you created file gigaviwer file
thats the file you can use with
that should work

hmm
i have to repair my ftp which complains about ssl then i easily can upload my self
AndyC
Dynamite Dan
Posts: 1408
Joined: Mon Nov 13, 2017 5:12 am

Re: gigaviewer

Post by AndyC »

Jbizzel wrote: Tue Jan 09, 2024 7:11 pm Thank you for sharing this - I've been wondering about it since you WOOT submission.

This is the code from the basic generated by imagetozxspec. Is this all that is needed for a simple viewer? Ran in USR0 mode.

Code: Select all

370 CLEAR 49151
380 POKE 23739,111 
390 OUT 32765,21 
400 LOAD "" CODE 49152 
410 OUT 32765,23 
420 LOAD "" CODE 49152 
430 PAUSE 1 
440 OUT 32765,16 
450 PAUSE 1 
460 OUT 32765,24
470 IF INKEY$<>"" THEN GO TO 370
480 GO TO 430
Of course I dont understand it LOL. Is "390 OUT 32765,21" etc changing the paged memory, then 440/460 changing the page that is the screen memory? IDK

I made a gigascreen image..

This is on real hardware. It just blows my tiny mind that this is possible.

Image
This is flipping the screen between two images every frame (well worse if you actually press a key but let's ignore that for a moment). It's a very similar effect, but I believe the actual "gigascreen" effect requires you to flip between screens every scanline, which in theory generates less flickering of colours.
User avatar
Jbizzel
Dynamite Dan
Posts: 1537
Joined: Mon May 04, 2020 4:34 pm
Location: Hull
Contact:

Re: gigaviewer

Post by Jbizzel »

But just to be clear, this image is flawless on my real spectrum and led TV, using an RGB scart cable. There is zero flicker.
AndyC
Dynamite Dan
Posts: 1408
Joined: Mon Nov 13, 2017 5:12 am

Re: gigaviewer

Post by AndyC »

Yes, a lot of LCD screens will, entirely as a side effect of their image processing, hide the flickering you'd normally see. The distinction is more obvious on an old school CRT.
C.Born
Manic Miner
Posts: 229
Joined: Sat Dec 09, 2017 4:09 pm

Re: gigaviewer

Post by C.Born »

LCD dont have a scanline, they preprocess in someway and switch memory on and off.
my viewer is old fashioned becouse the hardware is old fashioned, odear. :shock:
User avatar
Jbizzel
Dynamite Dan
Posts: 1537
Joined: Mon May 04, 2020 4:34 pm
Location: Hull
Contact:

Re: gigaviewer

Post by Jbizzel »

@C.Born on my real grey +2 with a divide 53.c card your woot giga demo doesn't seem to work. Only the first screen loads, then it crashes horribly if you press a key.
C.Born
Manic Miner
Posts: 229
Joined: Sat Dec 09, 2017 4:09 pm

Re: gigaviewer

Post by C.Born »

Jbizzel wrote: Fri Jan 12, 2024 7:31 am @C.Born on my real grey +2 with a divide 53.c card your woot giga demo doesn't seem to work. Only the first screen loads, then it crashes horribly if you press a key.
Sorry
it is toastrack aligned. but may i ask how the picture looks?
and you say that after the the key press it crashes, that means its a logistic problem which hopefully is easy to solve.
somewhere at the end off the todo list is making it work for all types, apereantly i have to make so pregress there.
todo: inputsystem alll types.
it has a keycheck routine and it HAD the keycheck outside the IM2 loop, Now I am rebuilding that per module and that is another timing-struggle but that why i do it aint it? :roll:

ps
a terrible way of seeing them all is skipping 2 pictures.
if you endup with a double picture, just rewind only one, on an emulator the spoilt ones hit a button, but you use DIVIDE? maybe then you CAB skip with a button instead off the FFWD + tape-counter
can it read MGT ?? i guess Rudy Biesma worked on it aswell ??

EDIT:
it tryed it on RealVirtualMachine and it hangs with a red screen and blakborder
the +2 starts with +3, so i think its a ramswitch thing
i have a deep look
cheers
User avatar
+3code
Manic Miner
Posts: 433
Joined: Sat Mar 19, 2022 7:40 am

Re: gigaviewer

Post by +3code »

IIRC the ram-paging scheme in 128/+2 grey is somehow different of that in the +3/+2A, the latter allows an all-ram mode, for example, but I'm not an expert. I think I've read somewhere the 128/+2 grey scheme allowed some type of gigascreen effect easier than the +3/+2A.
AndyC
Dynamite Dan
Posts: 1408
Joined: Mon Nov 13, 2017 5:12 am

Re: gigaviewer

Post by AndyC »

+3code wrote: Fri Jan 12, 2024 1:12 pm IIRC the ram-paging scheme in 128/+2 grey is somehow different of that in the +3/+2A, the latter allows an all-ram mode, for example, but I'm not an expert. I think I've read somewhere the 128/+2 grey scheme allowed some type of gigascreen effect easier than the +3/+2A.
The +2A/+3 paging mechanism is just an extension of the 128/+2 one, so I can't imagine a scenario where a gigascreen effect would be easier. Unless it was because of the floating bus effect, which it used to be assumed wasn't available on the +2A but the same thing has since been reproduced in a slightly different fashion.

If it's having issues on the older models, but not the +2A, my first suspicion would be the I register is pointing at contended RAM, as that can be a source of issues in that case.
C.Born
Manic Miner
Posts: 229
Joined: Sat Dec 09, 2017 4:09 pm

Re: gigaviewer

Post by C.Born »

AndyC wrote: Fri Jan 12, 2024 1:56 pm If it's having issues on the older models, but not the +2A, my first suspicion would be the I register is pointing at contended RAM, as that can be a source of issues in that case.
its reversed but thats somewhere the same
it was my second guess that IM 1 is wrong indeed
from above SECOND asm, there you find setpage

Code: Select all

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 + tpage
                  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

                  ld bc,(bigbel)    ;20t
doret             RET               ;10t exit
I had a code-fight before and i think I_register has to be set to '0' zero
then i need a trap
ld a,i
ld (MI1_a),a
but if another IM2 is running that will give a false answer
then i need a genuine check on the ROMS, there are several routines available, i hope that will do.
maybe there are some other things like amount off scanlines??
Post Reply