zxdiv: split more stuff out into dev/zx/
authorAlan Cox <alan@linux.intel.com>
Mon, 26 Nov 2018 13:55:03 +0000 (13:55 +0000)
committerAlan Cox <alan@linux.intel.com>
Mon, 26 Nov 2018 13:55:03 +0000 (13:55 +0000)
Share all the video and tricks code we can

Kernel/dev/zx/tricks.s [new file with mode: 0644]
Kernel/dev/zx/video.s [new file with mode: 0644]
Kernel/platform-zxdiv/loader.s [deleted file]
Kernel/platform-zxdiv/tricks.s
Kernel/platform-zxdiv/zxvideo.s

diff --git a/Kernel/dev/zx/tricks.s b/Kernel/dev/zx/tricks.s
new file mode 100644 (file)
index 0000000..7b259ac
--- /dev/null
@@ -0,0 +1,471 @@
+; Based on the Z80 Pack banked code
+;
+; Should unify this somewhat with lib/banked
+;
+
+        .module tricks
+
+        .globl _ptab_alloc
+        .globl _newproc
+        .globl _getproc
+        .globl _platform_monitor
+        .globl trap_illegal
+        .globl _platform_switchout
+        .globl _switchin
+       .globl _low_bank
+       .globl _dup_low_page
+        .globl _dofork
+        .globl _runticks
+        .globl unix_syscall_entry
+        .globl interrupt_handler
+       .globl current_map
+       .globl _ptab
+       .globl _swapper
+       .globl _int_disabled
+       .globl switch_bank
+
+        ; imported debug symbols
+        .globl outstring, outde, outhl, outbc, outnewline, outchar, outcharhex
+
+        .include "kernel.def"
+        .include "../kernel.def"
+
+        .area _COMMONMEM
+
+; Switchout switches out the current process, finds another that is READY,
+; possibly the same process, and switches it in.  When a process is
+; restarted after calling switchout, it thinks it has just returned
+; from switchout().
+_platform_switchout:
+        di
+        ; save machine state
+
+        ld hl, #0 ; return code set here is ignored, but _switchin can 
+        ; return from either _switchout OR _dofork, so they must both write 
+        ; U_DATA__U_SP with the following on the stack:
+        push hl ; return code
+        push ix
+        push iy
+
+       ld a,(current_map)
+       push af
+
+        ld (U_DATA__U_SP), sp ; this is where the SP is restored in _switchin
+
+       ;
+       ; We are now running on the sleeping process stack. The switchin
+       ; will simply go back to the saved SP above and discard anything
+       ; here
+       ;
+
+       ; Stash the uarea back into process memory
+       ld hl, (U_DATA__U_PAGE)
+       ld a, l
+       ld bc, #0x7ffd
+       or #BANK_BITS
+       out (c), a
+
+       ; This includes the stacks, so be careful on restore
+       ld hl, #U_DATA
+       ld de, #U_DATA_STASH
+       ld bc, #U_DATA__TOTALSIZE
+       ldir
+       ld a, (current_map)
+       or #BANK_BITS
+       ld bc, #0x7ffd
+       out (c), a
+
+        ; find another process to run (may select this one again)
+       push af
+        call _getproc
+       pop af          ; we can't optimise this as the linker
+                       ; is entitled to patch the 5 bytes here into a
+                       ; banked call
+        push hl
+       push af
+        call _switchin
+
+        ; we should never get here
+        call _platform_monitor
+
+badswitchmsg: .ascii "_switchin: FAIL"
+            .db 13, 10, 0
+
+_switchin:
+        di
+       pop hl  ; far padding
+        pop bc  ; return address
+        pop de  ; new process pointer
+;
+;      FIXME: do we actually *need* to restore the stack !
+;
+        push de ; restore stack
+        push bc ; restore stack
+       push hl ; far padding
+
+       push de
+        ld hl, #P_TAB__P_PAGE_OFFSET
+       add hl, de      ; process ptr
+       pop de
+       ;
+       ;       Get ourselves a valid private stack ASAP. We are going to
+       ;       copy udata around and our main stacks are in udata
+       ;
+       ld sp, #_swapstack
+
+        ld a, (hl)     ; 0 swapped, not zero is the bank for C000
+       or a
+       jr nz, not_swapped
+
+       ; Swap the process in (this may swap something else out first)
+       ; The second pushes are C function arguments. SDCC can trample
+       ; these
+
+       ; Turn this one once we have it all sorted and debugged
+       ; ei
+       ; xor a
+       ; ld (_int_disabled),a
+       push hl         ; Save
+       push de
+       push hl         ; Arguments
+       push de
+       push af
+       call _swapper
+       pop af
+       pop af
+       pop af
+       pop de          ; Restore
+       pop hl
+       ld a,#1
+       ld (_int_disabled),a
+       di
+       ld a, (hl)      ; We should now have a page assigned
+not_swapped:
+       ld hl,(U_DATA__U_PTAB)
+       or a
+       sbc hl,de
+; Turn this on once debugged
+;      jr z, skip_copyback
+
+       ; We are in DI so we can poke these directly but must not invoke
+       ; any code outside of common
+       or #BANK_BITS   ; ROM
+       ; Pages please !
+       ld bc, #0x7ffd
+       out (c), a
+
+       ;       Copy the stash from the user page back down into common
+       ;       The alternate registers are free - we use them for the
+       ;       block copy and for the flipper
+       ;
+       ;       FIXME: Add Tormod's optimisation from the 6809 tree
+       ;
+       exx
+       ld hl, #U_DATA_STASH
+       ld de, #U_DATA
+       ld bc, #U_DATA__TOTALSIZE
+       ldir
+       exx
+       ;
+       ;        Remap the kernel proper
+       ;
+
+       ld a, (current_map)
+       or #BANK_BITS
+       ld bc, #0x7ffd
+       out (c), a
+        
+       ;       Is our low data in 0x8000 already or do we need to flip
+       ;       it with bank 6. _low_bank holds the page pointer of the
+       ;       task owning the space
+
+       ld hl, (_low_bank)      ; who owns low memory
+       or a
+       sbc hl, de              ; preserve DE
+       jr z, nofliplow         ; skip the flip if we own low bank
+;
+;      Flip low banks over. Preserve DE
+;
+fliplow:
+       exx
+       ld hl, #0x8000
+       ld de, #0xc000
+       ld a, #6 + BANK_BITS
+       ld bc, #0x7ffd
+       out (c), a
+flip2:
+       ld b, #0                ; 256 bytes per outer loop (16K total)
+flip1:
+       ld c, (hl)
+       ld a, (de)
+       ex de, hl
+       ld (hl), c
+       ld (de), a
+       inc hl
+       inc de
+       djnz flip1
+       xor a
+       cp d                    ; Wrapped to 0x0000 ?
+       jr nz, flip1
+
+       ld a, (current_map)
+       or #BANK_BITS
+       ld bc, #0x7ffd
+       out (c), a
+       exx
+       ld (_low_bank), de      ; we own it now
+
+nofliplow:
+
+        ; check u_data->u_ptab matches what we wanted
+        ld hl, (U_DATA__U_PTAB) ; u_data->u_ptab
+        or a                    ; clear carry flag
+        sbc hl, de              ; subtract, result will be zero if DE == HL
+        jr nz, switchinfail
+
+       ; wants optimising up a bit
+       ld ix, (U_DATA__U_PTAB)
+        ; next_process->p_status = P_RUNNING
+        ld P_TAB__P_STATUS_OFFSET(ix), #P_RUNNING
+
+       ; Fix any moved page pointers
+       ; Just do one byte as that is all we use on this platform
+       ld a, P_TAB__P_PAGE_OFFSET(ix)
+       ld (U_DATA__U_PAGE), a
+        ; runticks = 0
+        ld hl, #0
+        ld (_runticks), hl
+
+        ; restore machine state -- note we may be returning from either
+        ; _switchout or _dofork
+        ld sp, (U_DATA__U_SP)
+
+       ;
+       ; We can now use the stack again
+       ;
+
+       pop af
+        pop iy
+        pop ix
+        pop hl ; return code
+
+       ; Make sure we have the right kernel bank to return to
+       call switch_bank
+
+        ; enable interrupts, if the ISR isn't already running
+        ld a, (U_DATA__U_ININTERRUPT)
+       ld (_int_disabled),a
+        or a
+        ret nz ; in ISR, leave interrupts off
+        ei
+        ret ; return with interrupts on
+
+switchinfail:
+       call outhl
+        ld hl, #badswitchmsg
+        call outstring
+       ; something went wrong and we didn't switch in what we asked for
+        jp _platform_monitor
+
+; Interrupts should be off when this is called
+_dup_low_page:
+       di                              ; FIXME: check callers properly
+       ld a, #0x06 + BANK_BITS         ; low page alternate
+       ld bc, #0x7ffd
+       out (c), a
+
+       ld hl, #0x8000                  ; fixed
+       ld de, #0xC000                  ; page we just mapped in
+       ld bc, #16384
+       ldir
+
+       ld a, (current_map)             ; restore mapping
+       or #BANK_BITS                   ; ROM bits
+       ld bc, #0x7ffd
+       out (c), a
+       ret
+
+
+;
+;      Called from _fork. We are in a syscall, the uarea is live as the
+;      parent uarea. The kernel is the mapped object.
+;
+_dofork:
+        ; always disconnect the vehicle battery before performing maintenance
+        di ; should already be the case ... belt and braces.
+
+       pop bc
+        pop de  ; return address
+        pop hl  ; new process p_tab*
+        push hl
+        push de
+       push bc
+
+        ld (fork_proc_ptr), hl
+
+        ; prepare return value in parent process -- HL = p->p_pid;
+        ld de, #P_TAB__P_PID_OFFSET
+        add hl, de
+        ld a, (hl)
+        inc hl
+        ld h, (hl)
+        ld l, a
+
+        ; Save the stack pointer and critical registers.
+        ; When this process (the parent) is switched back in, it will be as if
+        ; it returns with the value of the child's pid.
+        push hl ; HL still has p->p_pid from above, the return value in the parent
+        push ix
+        push iy
+
+       ld a,(current_map)
+       push af
+
+        ; save kernel stack pointer -- when it comes back in the parent we'll be in
+        ; _switchin which will immediately return (appearing to be _dofork()
+       ; returning) and with HL (ie return code) containing the child PID.
+        ; Hurray.
+        ld (U_DATA__U_SP), sp
+
+        ; now we're in a safe state for _switchin to return in the parent
+       ; process.
+
+       ; Need to write a new 16K bank copy here, then copy the live uarea
+       ; into the stash of the new process
+
+        ; --------- copy process ---------
+
+        ld hl, (fork_proc_ptr)
+       ld (_low_bank), hl              ;       low bank will become the child
+        ld de, #P_TAB__P_PAGE_OFFSET   ;       bank number
+        add hl, de
+        ; load p_page
+        ld c, (hl)
+       ld hl, (U_DATA__U_PAGE)
+       ld a, l
+
+       ;
+       ; Copy the high page via the bounce buffer
+       ;
+
+       call bankfork                   ;       do the bank to bank copy
+
+       ; FIXME: if we support small apps at C000-FBFF we need to tweak this
+       ; Now copy the 0x8000-0xBFFF area directly
+
+       ld a, #0x06 + BANK_BITS         ;       low page alternate
+       ld bc, #0x7ffd
+       out (c), a
+
+       ld hl, #0x8000                  ;       Fixed
+       ld de, #0xC000                  ;       Page we just mapped in
+       ld bc, #16384
+       ldir
+
+       ; Copy done
+
+       ld a, (U_DATA__U_PAGE)  ; parent memory
+       or #BANK_BITS           ; get the right ROMs
+       ld bc, #0x7ffd
+       out (c), a              ; Switch context to parent in 0xC000+
+
+       ; We are going to copy the uarea into the parents uarea stash
+       ; we must not touch the parent uarea after this point, any
+       ; changes only affect the child
+       ld hl, #U_DATA          ; copy the udata from common into the
+       ld de, #U_DATA_STASH    ; target process
+       ld bc, #U_DATA__TOTALSIZE
+       ldir
+
+       ;
+       ; And back into the kernel
+       ;
+       ld bc, #0x7ffd
+       ld a, (current_map)
+       or #BANK_BITS
+       out (c), a
+        ; now the copy operation is complete we can get rid of the stuff
+        ; _switchin will be expecting from our copy of the stack.
+
+        pop bc
+        pop iy
+        pop ix
+       pop bc
+
+        ; Make a new process table entry, etc.
+        ld  hl, (fork_proc_ptr)
+        push hl
+       push af
+        call _newproc
+       pop af
+        pop bc 
+
+        ; runticks = 0;
+        ld hl, #0
+        ld (_runticks), hl
+        ; in the child process, fork() returns zero.
+       ;
+       ; And we exit, with the kernel mapped, the child now being deemed
+       ; to be the live uarea. The parent is frozen in time and space as
+       ; if it had done a switchout().
+        ret
+
+;
+;      This is related so we will keep it here. Copy the process memory
+;      for a fork. a is the page base of the parent, c of the child
+;      (this API will be insufficient once we have chmem and proper use of
+;      banks - as well as needing to support fork to disk)
+;
+;      Assumption - fits into a fixed number of whole 256 byte blocks
+;
+;
+;      Note: this needs reviewing. We now have a lot more program memory
+;      we can use with a lazy copying model
+;
+bankfork:
+       or #BANK_BITS           ; ROM bits for the bank
+       ld b, #0x3E             ; 64 x 256 minus 2 sets for the uarea stash/irqs
+       ld hl, #0xC000          ; base of memory to fork (vectors included)
+bankfork_1:
+       push bc                 ; Save our counter and also child offset
+       push hl
+       ld bc, #0x7ffd
+       out (c), a              ; switch to parent bank
+       ld de, #bouncebuffer
+       ld bc, #256
+       ldir                    ; copy into the bounce buffer
+       pop de                  ; recover source of copy to bounce
+                               ; as destination in new bank
+       pop bc                  ; recover child port number
+       push bc
+       ld b, a                 ; save the parent bank id
+       ld a, c                 ; switch to the child
+       push bc                 ; save the bank pointers
+       ld bc, #0x7ffd
+       or #BANK_BITS           ; ROM bits
+       out (c), a
+       ld hl, #bouncebuffer
+       ld bc, #256
+       ldir                    ; copy into the child
+       pop bc                  ; recover the bank pointers
+       ex de, hl               ; destination is now source for next bank
+       ld a, b                 ; parent back is wanted in a
+       pop bc
+       djnz bankfork_1         ; rinse, repeat
+       ret
+;
+;      For the moment
+;
+       .area _COMMONDATA
+bouncebuffer:
+       .ds 256
+;      We can keep a stack in common because we will complete our
+;      use of it before we switch common block. In this case we have
+;      a true common so it's even easier. We never use both at once
+;      so share with bouncebuffer
+_swapstack:
+_low_bank:
+       .dw _ptab                       ; Init starts owning this
+
+fork_proc_ptr:
+       .dw 0 ; (C type is struct p_tab *) -- address of child process p_tab entry
diff --git a/Kernel/dev/zx/video.s b/Kernel/dev/zx/video.s
new file mode 100644 (file)
index 0000000..ef87e25
--- /dev/null
@@ -0,0 +1,371 @@
+;
+;        zx128 vt primitives
+;
+        ; exported symbols
+        .globl zx_plot_char
+        .globl zx_scroll_down
+        .globl zx_scroll_up
+        .globl zx_cursor_on
+        .globl zx_cursor_off
+       .globl zx_cursor_disable
+        .globl zx_clear_lines
+        .globl zx_clear_across
+        .globl zx_do_beep
+       .globl _fontdata_8x8
+       .globl _curattr
+       .globl _vtattr
+
+videopos:
+        ld a,e
+        and #7
+        rrca
+        rrca
+        rrca 
+        add a,d
+        ld d,e
+        ld e,a
+        ld a,d
+        and #0x18
+        or #0x40           ; Standard screen
+        ld d,a
+        ret
+
+videoattr:
+       ;                       32 x E + D into HL
+       ld a,e
+       rrca
+       rrca
+       rrca                    ; A is now 32xE with the top bits overflowed
+                               ; into the low 2 bits
+       ld l,a
+       and #3                  ; Extract the low 2 bits for the high
+       add #0x58               ; Attributes start 0x5800
+       ld h,a
+       ld a,l
+       and #0xE0               ; mask the bits that are valid
+       add d                   ; add the low 5 bits from D
+       ld l,a                  ; and done (the add can't overflow)
+       ret
+
+       .if ZXVID_ONLY
+_plot_char:
+       .endif
+zx_plot_char:
+       pop iy
+        pop hl
+        pop de              ; D = x E = y
+        pop bc
+        push bc
+        push de
+        push hl
+       push iy
+
+       push de
+        call videopos
+
+        ld b, #0            ; calculating offset in font table
+        ld a, c
+       or a                ; clear carry
+        rla
+        rl b
+        rla
+        rl b
+        rla
+        rl b
+        ld c, a
+
+        ld hl, #_fontdata_8x8-32*8    ; font
+        add hl, bc          ; hl points to first byte of char data
+
+       ; We do underline for now - not clear italic or bold are useful
+       ; with the font we have.
+       ld bc,(_vtattr)     ; c is vt attributes
+
+        ; printing
+plot_char_loop:
+        ld a, (hl)
+        ld (de), a
+        inc l               ; next byte of char data
+        inc d               ; next screen line
+
+        ld a, (hl)
+        ld (de), a
+        inc l               ; next byte of char data
+        inc d               ; next screen line
+
+        ld a, (hl)
+        ld (de), a
+        inc l               ; next byte of char data
+        inc d               ; next screen line
+
+        ld a, (hl)
+        ld (de), a
+        inc l               ; next byte of char data
+        inc d               ; next screen line
+
+        ld a, (hl)
+        ld (de), a
+        inc l               ; next byte of char data
+        inc d               ; next screen line
+
+        ld a, (hl)
+        ld (de), a
+        inc l               ; next byte of char data
+        inc d               ; next screen line
+
+        ld a, (hl)
+        ld (de), a
+        inc l               ; next byte of char data
+        inc d               ; next screen line
+
+        ld a, (hl)
+       bit 1,c             ; underline ?
+       jr nz, last_ul
+plot_attr:
+        ld (de), a
+
+       pop de
+       call videoattr
+       ld a,(_curattr)
+       ld (hl),a
+        ret
+
+last_ul:
+       ld a,#0xff
+       jr plot_attr
+
+       .if ZXVID_ONLY
+_clear_lines:
+       .endif
+zx_clear_lines:
+       pop bc
+        pop hl
+        pop de              ; E = line, D = count
+        push de
+        push hl
+       push bc
+       ; This way we handle 0 correctly
+       inc d
+       jr nextline
+
+clear_next_line:
+        push de
+        ld d, #0            ; from the column #0
+        ld b, d             ; b = 0
+        ld c, #32           ; clear 32 cols
+        push bc
+        push de
+       push af
+        call _clear_across
+       pop af
+        pop hl              ; clear stack
+        pop hl
+
+        pop de
+        inc e
+nextline:
+        dec d
+        jr nz, clear_next_line
+
+        ret
+
+
+       .if ZXVID_ONLY
+_clear_across:
+       .endif
+zx_clear_across:
+       pop iy
+        pop hl
+        pop de              ; DE = coords 
+        pop bc              ; C = count
+        push bc
+        push de
+        push hl
+       push iy
+       ld a,c
+       or a
+       ret z               ; No work to do - bail out
+       push de
+       push bc
+        call videopos       ; first pixel line of first character in DE
+        push de
+        pop hl              ; copy to hl
+        xor a
+
+        ; no boundary checks. Assuming that D + C < SCREEN_WIDTH
+
+clear_line:
+        ld b, #8            ; 8 pixel lines to clear for this char
+clear_char:
+        ld (de), a
+        inc d
+        djnz clear_char
+
+        ex de, hl
+        inc de
+        push de
+        pop hl
+
+        dec c
+        jr nz, clear_line
+       pop bc
+       pop de
+       call videoattr
+       ld a,(_curattr)
+       ld b,c
+setattr:
+       ld (hl),a
+       inc hl
+       djnz setattr
+        ret
+
+copy_line:
+        ; HL - source, DE - destination
+
+        ; convert line coordinates to screen coordinates both for DE and HL
+        push de
+        ex de, hl
+        call videopos
+        ex de, hl
+        pop de
+        call videopos
+
+        ld c, #8
+
+copy_line_nextchar:
+        push hl
+        push de
+
+        ld b, #32
+
+copy_pixel_line:
+        ld a, (hl)
+        ld (de), a
+        inc e
+        inc l
+        djnz copy_pixel_line
+
+        pop de
+        pop hl
+        inc d
+        inc h
+        dec c
+        jr nz, copy_line_nextchar
+        ret
+
+        ; TODO: the LDIR way should be much faster
+
+       .if ZXVID_ONLY
+_scroll_down:
+       .endif
+zx_scroll_down:
+        ; set HL = (0,22), DE = (0, 23)
+        xor a
+        ld d, a
+        ld h, a
+        ld l, #22
+        ld e, #23
+        ld c, #23           ; 23 lines to move
+
+loop_scroll_down:
+        push hl
+        push de
+        push bc
+
+        call copy_line
+
+        pop bc
+        pop de
+        pop hl
+
+        dec l
+        dec e
+        dec c
+        jr nz, loop_scroll_down
+
+       ; Attributes
+       ld hl,#0x5ADF
+       ld de,#0x5AFF
+       ld bc,#0x02E0
+       lddr
+
+        ret
+
+
+       .if ZXVID_ONLY
+_scroll_up:
+       .endif
+zx_scroll_up:
+        ; set HL = (0,1), DE = (0, 0)
+        xor a
+        ld d, a
+        ld e, a
+        ld h, a
+        ld l, #1
+        ld c, #23           ; 23 lines to move
+
+loop_scroll_up:
+        push hl
+        push de
+        push bc
+
+        call copy_line
+
+        pop bc
+        pop de
+        pop hl
+
+        inc l
+        inc e
+        dec c
+        jr nz, loop_scroll_up
+
+       ld hl,#0x5820
+       ld de,#0x5800
+       ld bc,#0x02E0
+       ldir
+        ret
+
+       .if ZXVID_ONLY
+_cursor_on:
+       .endif
+zx_cursor_on:
+       pop bc
+        pop hl
+        pop de
+        push de
+        push hl
+       push bc
+        ld (cursorpos), de
+
+        call videopos
+        ld a, #7
+        add a, d
+        ld d, a
+        ld a, #0xFF
+        ld (de), a
+        ret
+       .if ZXVID_ONLY
+_cursor_disable:
+_cursor_off:
+       .endif
+zx_cursor_disable:
+zx_cursor_off:
+        ld de, (cursorpos)
+        call videopos
+        ld a, #7
+        add a, d
+        ld d, a
+        xor a
+        ld (de), a
+
+       .if ZXVID_ONLY
+_do_beep:
+       .endif
+zx_do_beep:
+        ret
+
+        .area _DATA
+
+cursorpos:
+        .dw 0
diff --git a/Kernel/platform-zxdiv/loader.s b/Kernel/platform-zxdiv/loader.s
deleted file mode 100644 (file)
index a866181..0000000
+++ /dev/null
@@ -1,199 +0,0 @@
-;
-;      DivIDE is a bit of a pain as all the firmware is designed around
-;      ROM BASIC and snapshots. We trick it by providing a fake BOOT.BIN.
-;      Fatware thinks that this is the Fatware code it wants to put in
-;      bank3 and then lock. In fact it's our loader which it will load
-;      and lock for us.
-;
-       .area BOOT      (ABS)
-
-       .globl null_handler
-       .globl unix_syscall_entry
-       .globl interrupt_handler
-
-       .org 0
-
-;
-;      We don't have a JP at 0 as we'd like so our low level code needs
-;      to avoid that check
-;
-loader:
-       di
-       ld a,#0x80
-       out (0xE3),a
-       ; Page the EEPROM in and control transfers there
-       ; not to the jp below
-loader5:
-       ; This is where the EEPROM calls us
-       jp start
-rst_8:
-       .ds 8
-rst_10:
-       .ds 8
-rst_18:
-       .ds 8
-rst_20:
-       .ds 8
-rst_28:
-       .ds 8
-rst_30:
-       jp unix_syscall_entry
-       .ds 5
-rst_38:
-       jp interrupt_handler
-       .ds 0x66-0x3B
-nmi:   ret             ; magic...
-       retn
-
-;
-;      Load and go
-;
-start:
-       ld bc,#0x7ffd
-
-       ; Map some RAM (must not be RAM2) in 2000-3FFF
-       ld a,#0x40
-       out (0xE3),a
-
-       ; Stack in the first 512 bytes of our data space
-       ld sp,#0x2200
-
-       ; Select the shadow screen bank
-       ld a,#0x17
-       out (c), a
-
-       ; Clear the shadow screen
-       ld hl,#0xc000
-       ld de,#0xc001
-       ld bc,#6144
-       ld (hl),#0
-       ldir
-       ; Attributes to green writing on black
-       ld (hl),#4
-       ld bc,#767
-       ldir
-
-       ; Black border
-       xor a
-       out (254),a
-
-       ; Shadow screen on, bank 0 back at C000-FFFF            
-       ld bc,#0x7ffd
-       ld a,#0x18
-       out (c),a
-
-       ; Screen is now on bank 7
-       ; Memory is on bank 0
-
-       ; Put some RAM in 0x2000-3FFF and keep us locked in the low 8K
-       ; Do not use #0x42, this is magic for allram mode on later DivIDE
-       ld a,#0x40
-       out (0xE3),a
-       ;
-       ;       Ensure the master drive is selected
-       ;
-wait1:
-       in a,(191)
-       rla
-       jr c, wait1
-       ld a,#0xE0
-       out (187),a
-       nop
-wait2:
-       in a,(191)
-       and #0xC0
-       cp #0x40                ; want busy off, drdy
-       jr nz, wait2
-
-       ;
-       ; Load sectors. We shortcut stuff here because we never
-       ; load over 256 sectors
-       ;
-       ;
-       ; We load 112 sectors into 2000-FFFF using bank 0 as the top bank
-       ; We then load 32 sectors into the 16K at C000-FFFF bank 1
-       ; And finally the same for bank 7
-       ; 0x2000 should start ZB then the execution address
-       ;
-       ; For simplicity we don't bother with a stack, we just use IX
-       ;
-       xor a                   ; LBA 0
-       out (175),a
-       out (179),a
-       ld de,#0x7001           ; Load 111 sectors (2200-FFFF)
-                               ; from sector 1
-       ld hl,#0x2200           ; Starting address to load
-       call load_loop
-
-       ld a,#0x19              ; Select bank 1
-       ld bc,#0x7ffd
-       ld d,#0x20              ; Load 32 sectors (C000-FFFF)
-       ld hl,#0xc000
-       call load_loop
-
-       ld a,#0x1F              ; Select bank 7
-       ld bc,#0x7ffd
-       out (c),a
-       ld d,#0x20              ; Load 32 sectors (C000-FFFF)
-       ld hl,#0xC000
-       call load_loop
-
-       ld a,#0x18
-       ld bc,#0x7ffd
-       out (c),a               ; Switch back to bank 0
-       ld hl,#0x2200
-       ; 0x2200 should start with a signature of ZB then the execute
-       ; address
-       ld a,(hl)
-       cp #'Z'
-       jr nz, failed
-       inc hl
-       ld a,(hl)
-       cp #'B'
-       jr nz, failed
-       inc hl
-       ld a,(hl)
-       inc hl
-       ld h,(hl)
-       ld l,a
-       jp (hl)
-
-load_loop:
-       ld a,e
-       inc e
-       out (183),a             ; sector number to load
-       ld a,#1                 ; load one sector
-       out (171),a
-       ld a,#0x20              ; READ
-       out (191),a
-       nop
-wait3:
-       in a, (191)
-       rlca
-       jr c, wait3             ; Busy
-       bit 4,a                 ; DRQ ?
-       jr z, failed            ; Nope - bad
-       ld bc,#163              ; Data port
-       inir
-       inir
-       dec d
-       jr nz, load_loop
-       ret
-
-failed:
-       ld hl,#1
-       jp OutJPHL              ; Into Spectrum ROM and reboot
-
-
-       .area BOOT1FF7
-
-       ;
-       ; For compatibility with FatWare
-       ;
-OutEI: ei
-OutRet:        ret
-OutJPHL:       jp (hl)
-
-       .area BOOT1FFE
-RomSign:
-       .db 0,14
index 7b259ac..c333910 100644 (file)
@@ -1,471 +1,2 @@
-; Based on the Z80 Pack banked code
-;
-; Should unify this somewhat with lib/banked
-;
 
-        .module tricks
-
-        .globl _ptab_alloc
-        .globl _newproc
-        .globl _getproc
-        .globl _platform_monitor
-        .globl trap_illegal
-        .globl _platform_switchout
-        .globl _switchin
-       .globl _low_bank
-       .globl _dup_low_page
-        .globl _dofork
-        .globl _runticks
-        .globl unix_syscall_entry
-        .globl interrupt_handler
-       .globl current_map
-       .globl _ptab
-       .globl _swapper
-       .globl _int_disabled
-       .globl switch_bank
-
-        ; imported debug symbols
-        .globl outstring, outde, outhl, outbc, outnewline, outchar, outcharhex
-
-        .include "kernel.def"
-        .include "../kernel.def"
-
-        .area _COMMONMEM
-
-; Switchout switches out the current process, finds another that is READY,
-; possibly the same process, and switches it in.  When a process is
-; restarted after calling switchout, it thinks it has just returned
-; from switchout().
-_platform_switchout:
-        di
-        ; save machine state
-
-        ld hl, #0 ; return code set here is ignored, but _switchin can 
-        ; return from either _switchout OR _dofork, so they must both write 
-        ; U_DATA__U_SP with the following on the stack:
-        push hl ; return code
-        push ix
-        push iy
-
-       ld a,(current_map)
-       push af
-
-        ld (U_DATA__U_SP), sp ; this is where the SP is restored in _switchin
-
-       ;
-       ; We are now running on the sleeping process stack. The switchin
-       ; will simply go back to the saved SP above and discard anything
-       ; here
-       ;
-
-       ; Stash the uarea back into process memory
-       ld hl, (U_DATA__U_PAGE)
-       ld a, l
-       ld bc, #0x7ffd
-       or #BANK_BITS
-       out (c), a
-
-       ; This includes the stacks, so be careful on restore
-       ld hl, #U_DATA
-       ld de, #U_DATA_STASH
-       ld bc, #U_DATA__TOTALSIZE
-       ldir
-       ld a, (current_map)
-       or #BANK_BITS
-       ld bc, #0x7ffd
-       out (c), a
-
-        ; find another process to run (may select this one again)
-       push af
-        call _getproc
-       pop af          ; we can't optimise this as the linker
-                       ; is entitled to patch the 5 bytes here into a
-                       ; banked call
-        push hl
-       push af
-        call _switchin
-
-        ; we should never get here
-        call _platform_monitor
-
-badswitchmsg: .ascii "_switchin: FAIL"
-            .db 13, 10, 0
-
-_switchin:
-        di
-       pop hl  ; far padding
-        pop bc  ; return address
-        pop de  ; new process pointer
-;
-;      FIXME: do we actually *need* to restore the stack !
-;
-        push de ; restore stack
-        push bc ; restore stack
-       push hl ; far padding
-
-       push de
-        ld hl, #P_TAB__P_PAGE_OFFSET
-       add hl, de      ; process ptr
-       pop de
-       ;
-       ;       Get ourselves a valid private stack ASAP. We are going to
-       ;       copy udata around and our main stacks are in udata
-       ;
-       ld sp, #_swapstack
-
-        ld a, (hl)     ; 0 swapped, not zero is the bank for C000
-       or a
-       jr nz, not_swapped
-
-       ; Swap the process in (this may swap something else out first)
-       ; The second pushes are C function arguments. SDCC can trample
-       ; these
-
-       ; Turn this one once we have it all sorted and debugged
-       ; ei
-       ; xor a
-       ; ld (_int_disabled),a
-       push hl         ; Save
-       push de
-       push hl         ; Arguments
-       push de
-       push af
-       call _swapper
-       pop af
-       pop af
-       pop af
-       pop de          ; Restore
-       pop hl
-       ld a,#1
-       ld (_int_disabled),a
-       di
-       ld a, (hl)      ; We should now have a page assigned
-not_swapped:
-       ld hl,(U_DATA__U_PTAB)
-       or a
-       sbc hl,de
-; Turn this on once debugged
-;      jr z, skip_copyback
-
-       ; We are in DI so we can poke these directly but must not invoke
-       ; any code outside of common
-       or #BANK_BITS   ; ROM
-       ; Pages please !
-       ld bc, #0x7ffd
-       out (c), a
-
-       ;       Copy the stash from the user page back down into common
-       ;       The alternate registers are free - we use them for the
-       ;       block copy and for the flipper
-       ;
-       ;       FIXME: Add Tormod's optimisation from the 6809 tree
-       ;
-       exx
-       ld hl, #U_DATA_STASH
-       ld de, #U_DATA
-       ld bc, #U_DATA__TOTALSIZE
-       ldir
-       exx
-       ;
-       ;        Remap the kernel proper
-       ;
-
-       ld a, (current_map)
-       or #BANK_BITS
-       ld bc, #0x7ffd
-       out (c), a
-        
-       ;       Is our low data in 0x8000 already or do we need to flip
-       ;       it with bank 6. _low_bank holds the page pointer of the
-       ;       task owning the space
-
-       ld hl, (_low_bank)      ; who owns low memory
-       or a
-       sbc hl, de              ; preserve DE
-       jr z, nofliplow         ; skip the flip if we own low bank
-;
-;      Flip low banks over. Preserve DE
-;
-fliplow:
-       exx
-       ld hl, #0x8000
-       ld de, #0xc000
-       ld a, #6 + BANK_BITS
-       ld bc, #0x7ffd
-       out (c), a
-flip2:
-       ld b, #0                ; 256 bytes per outer loop (16K total)
-flip1:
-       ld c, (hl)
-       ld a, (de)
-       ex de, hl
-       ld (hl), c
-       ld (de), a
-       inc hl
-       inc de
-       djnz flip1
-       xor a
-       cp d                    ; Wrapped to 0x0000 ?
-       jr nz, flip1
-
-       ld a, (current_map)
-       or #BANK_BITS
-       ld bc, #0x7ffd
-       out (c), a
-       exx
-       ld (_low_bank), de      ; we own it now
-
-nofliplow:
-
-        ; check u_data->u_ptab matches what we wanted
-        ld hl, (U_DATA__U_PTAB) ; u_data->u_ptab
-        or a                    ; clear carry flag
-        sbc hl, de              ; subtract, result will be zero if DE == HL
-        jr nz, switchinfail
-
-       ; wants optimising up a bit
-       ld ix, (U_DATA__U_PTAB)
-        ; next_process->p_status = P_RUNNING
-        ld P_TAB__P_STATUS_OFFSET(ix), #P_RUNNING
-
-       ; Fix any moved page pointers
-       ; Just do one byte as that is all we use on this platform
-       ld a, P_TAB__P_PAGE_OFFSET(ix)
-       ld (U_DATA__U_PAGE), a
-        ; runticks = 0
-        ld hl, #0
-        ld (_runticks), hl
-
-        ; restore machine state -- note we may be returning from either
-        ; _switchout or _dofork
-        ld sp, (U_DATA__U_SP)
-
-       ;
-       ; We can now use the stack again
-       ;
-
-       pop af
-        pop iy
-        pop ix
-        pop hl ; return code
-
-       ; Make sure we have the right kernel bank to return to
-       call switch_bank
-
-        ; enable interrupts, if the ISR isn't already running
-        ld a, (U_DATA__U_ININTERRUPT)
-       ld (_int_disabled),a
-        or a
-        ret nz ; in ISR, leave interrupts off
-        ei
-        ret ; return with interrupts on
-
-switchinfail:
-       call outhl
-        ld hl, #badswitchmsg
-        call outstring
-       ; something went wrong and we didn't switch in what we asked for
-        jp _platform_monitor
-
-; Interrupts should be off when this is called
-_dup_low_page:
-       di                              ; FIXME: check callers properly
-       ld a, #0x06 + BANK_BITS         ; low page alternate
-       ld bc, #0x7ffd
-       out (c), a
-
-       ld hl, #0x8000                  ; fixed
-       ld de, #0xC000                  ; page we just mapped in
-       ld bc, #16384
-       ldir
-
-       ld a, (current_map)             ; restore mapping
-       or #BANK_BITS                   ; ROM bits
-       ld bc, #0x7ffd
-       out (c), a
-       ret
-
-
-;
-;      Called from _fork. We are in a syscall, the uarea is live as the
-;      parent uarea. The kernel is the mapped object.
-;
-_dofork:
-        ; always disconnect the vehicle battery before performing maintenance
-        di ; should already be the case ... belt and braces.
-
-       pop bc
-        pop de  ; return address
-        pop hl  ; new process p_tab*
-        push hl
-        push de
-       push bc
-
-        ld (fork_proc_ptr), hl
-
-        ; prepare return value in parent process -- HL = p->p_pid;
-        ld de, #P_TAB__P_PID_OFFSET
-        add hl, de
-        ld a, (hl)
-        inc hl
-        ld h, (hl)
-        ld l, a
-
-        ; Save the stack pointer and critical registers.
-        ; When this process (the parent) is switched back in, it will be as if
-        ; it returns with the value of the child's pid.
-        push hl ; HL still has p->p_pid from above, the return value in the parent
-        push ix
-        push iy
-
-       ld a,(current_map)
-       push af
-
-        ; save kernel stack pointer -- when it comes back in the parent we'll be in
-        ; _switchin which will immediately return (appearing to be _dofork()
-       ; returning) and with HL (ie return code) containing the child PID.
-        ; Hurray.
-        ld (U_DATA__U_SP), sp
-
-        ; now we're in a safe state for _switchin to return in the parent
-       ; process.
-
-       ; Need to write a new 16K bank copy here, then copy the live uarea
-       ; into the stash of the new process
-
-        ; --------- copy process ---------
-
-        ld hl, (fork_proc_ptr)
-       ld (_low_bank), hl              ;       low bank will become the child
-        ld de, #P_TAB__P_PAGE_OFFSET   ;       bank number
-        add hl, de
-        ; load p_page
-        ld c, (hl)
-       ld hl, (U_DATA__U_PAGE)
-       ld a, l
-
-       ;
-       ; Copy the high page via the bounce buffer
-       ;
-
-       call bankfork                   ;       do the bank to bank copy
-
-       ; FIXME: if we support small apps at C000-FBFF we need to tweak this
-       ; Now copy the 0x8000-0xBFFF area directly
-
-       ld a, #0x06 + BANK_BITS         ;       low page alternate
-       ld bc, #0x7ffd
-       out (c), a
-
-       ld hl, #0x8000                  ;       Fixed
-       ld de, #0xC000                  ;       Page we just mapped in
-       ld bc, #16384
-       ldir
-
-       ; Copy done
-
-       ld a, (U_DATA__U_PAGE)  ; parent memory
-       or #BANK_BITS           ; get the right ROMs
-       ld bc, #0x7ffd
-       out (c), a              ; Switch context to parent in 0xC000+
-
-       ; We are going to copy the uarea into the parents uarea stash
-       ; we must not touch the parent uarea after this point, any
-       ; changes only affect the child
-       ld hl, #U_DATA          ; copy the udata from common into the
-       ld de, #U_DATA_STASH    ; target process
-       ld bc, #U_DATA__TOTALSIZE
-       ldir
-
-       ;
-       ; And back into the kernel
-       ;
-       ld bc, #0x7ffd
-       ld a, (current_map)
-       or #BANK_BITS
-       out (c), a
-        ; now the copy operation is complete we can get rid of the stuff
-        ; _switchin will be expecting from our copy of the stack.
-
-        pop bc
-        pop iy
-        pop ix
-       pop bc
-
-        ; Make a new process table entry, etc.
-        ld  hl, (fork_proc_ptr)
-        push hl
-       push af
-        call _newproc
-       pop af
-        pop bc 
-
-        ; runticks = 0;
-        ld hl, #0
-        ld (_runticks), hl
-        ; in the child process, fork() returns zero.
-       ;
-       ; And we exit, with the kernel mapped, the child now being deemed
-       ; to be the live uarea. The parent is frozen in time and space as
-       ; if it had done a switchout().
-        ret
-
-;
-;      This is related so we will keep it here. Copy the process memory
-;      for a fork. a is the page base of the parent, c of the child
-;      (this API will be insufficient once we have chmem and proper use of
-;      banks - as well as needing to support fork to disk)
-;
-;      Assumption - fits into a fixed number of whole 256 byte blocks
-;
-;
-;      Note: this needs reviewing. We now have a lot more program memory
-;      we can use with a lazy copying model
-;
-bankfork:
-       or #BANK_BITS           ; ROM bits for the bank
-       ld b, #0x3E             ; 64 x 256 minus 2 sets for the uarea stash/irqs
-       ld hl, #0xC000          ; base of memory to fork (vectors included)
-bankfork_1:
-       push bc                 ; Save our counter and also child offset
-       push hl
-       ld bc, #0x7ffd
-       out (c), a              ; switch to parent bank
-       ld de, #bouncebuffer
-       ld bc, #256
-       ldir                    ; copy into the bounce buffer
-       pop de                  ; recover source of copy to bounce
-                               ; as destination in new bank
-       pop bc                  ; recover child port number
-       push bc
-       ld b, a                 ; save the parent bank id
-       ld a, c                 ; switch to the child
-       push bc                 ; save the bank pointers
-       ld bc, #0x7ffd
-       or #BANK_BITS           ; ROM bits
-       out (c), a
-       ld hl, #bouncebuffer
-       ld bc, #256
-       ldir                    ; copy into the child
-       pop bc                  ; recover the bank pointers
-       ex de, hl               ; destination is now source for next bank
-       ld a, b                 ; parent back is wanted in a
-       pop bc
-       djnz bankfork_1         ; rinse, repeat
-       ret
-;
-;      For the moment
-;
-       .area _COMMONDATA
-bouncebuffer:
-       .ds 256
-;      We can keep a stack in common because we will complete our
-;      use of it before we switch common block. In this case we have
-;      a true common so it's even easier. We never use both at once
-;      so share with bouncebuffer
-_swapstack:
-_low_bank:
-       .dw _ptab                       ; Init starts owning this
-
-fork_proc_ptr:
-       .dw 0 ; (C type is struct p_tab *) -- address of child process p_tab entry
+       .include "../dev/zx/tricks.s"
index 509b0b8..78b4051 100644 (file)
        .globl _curattr
        .globl _vtattr
 
-        .area _VIDEO
-
-        ; colors are ignored everywhere for now
-
-videopos:
-        ld a,e
-        and #7
-        rrca
-        rrca
-        rrca 
-        add a,d
-        ld d,e
-        ld e,a
-        ld a,d
-        and #0x18
-        or #0x40           ; Standard screen
-        ld d,a
-        ret
-
-videoattr:
-       ;                       32 x E + D into HL
-       ld a,e
-       rrca
-       rrca
-       rrca                    ; A is now 32xE with the top bits overflowed
-                               ; into the low 2 bits
-       ld l,a
-       and #3                  ; Extract the low 2 bits for the high
-       add #0x58               ; Attributes start 0x5800
-       ld h,a
-       ld a,l
-       and #0xE0               ; mask the bits that are valid
-       add d                   ; add the low 5 bits from D
-       ld l,a                  ; and done (the add can't overflow)
-       ret
-
-_plot_char:
-       pop iy
-        pop hl
-        pop de              ; D = x E = y
-        pop bc
-        push bc
-        push de
-        push hl
-       push iy
-
-       push de
-        call videopos
-
-        ld b, #0            ; calculating offset in font table
-        ld a, c
-       or a                ; clear carry
-        rla
-        rl b
-        rla
-        rl b
-        rla
-        rl b
-        ld c, a
-
-        ld hl, #_fontdata_8x8-32*8    ; font
-        add hl, bc          ; hl points to first byte of char data
-
-       ; We do underline for now - not clear italic or bold are useful
-       ; with the font we have.
-       ld bc,(_vtattr)     ; c is vt attributes
-
-        ; printing
-plot_char_loop:
-        ld a, (hl)
-        ld (de), a
-        inc l               ; next byte of char data
-        inc d               ; next screen line
-
-        ld a, (hl)
-        ld (de), a
-        inc l               ; next byte of char data
-        inc d               ; next screen line
-
-        ld a, (hl)
-        ld (de), a
-        inc l               ; next byte of char data
-        inc d               ; next screen line
-
-        ld a, (hl)
-        ld (de), a
-        inc l               ; next byte of char data
-        inc d               ; next screen line
-
-        ld a, (hl)
-        ld (de), a
-        inc l               ; next byte of char data
-        inc d               ; next screen line
-
-        ld a, (hl)
-        ld (de), a
-        inc l               ; next byte of char data
-        inc d               ; next screen line
-
-        ld a, (hl)
-        ld (de), a
-        inc l               ; next byte of char data
-        inc d               ; next screen line
-
-        ld a, (hl)
-       bit 1,c             ; underline ?
-       jr nz, last_ul
-plot_attr:
-        ld (de), a
-
-       pop de
-       call videoattr
-       ld a,(_curattr)
-       ld (hl),a
-        ret
-
-last_ul:
-       ld a,#0xff
-       jr plot_attr
-
-_clear_lines:
-       pop bc
-        pop hl
-        pop de              ; E = line, D = count
-        push de
-        push hl
-       push bc
-       ; This way we handle 0 correctly
-       inc d
-       jr nextline
-
-clear_next_line:
-        push de
-        ld d, #0            ; from the column #0
-        ld b, d             ; b = 0
-        ld c, #32           ; clear 32 cols
-        push bc
-        push de
-       push af
-        call _clear_across
-       pop af
-        pop hl              ; clear stack
-        pop hl
-
-        pop de
-        inc e
-nextline:
-        dec d
-        jr nz, clear_next_line
-
-        ret
-
-
-_clear_across:
-       pop iy
-        pop hl
-        pop de              ; DE = coords 
-        pop bc              ; C = count
-        push bc
-        push de
-        push hl
-       push iy
-       ld a,c
-       or a
-       ret z               ; No work to do - bail out
-       push de
-       push bc
-        call videopos       ; first pixel line of first character in DE
-        push de
-        pop hl              ; copy to hl
-        xor a
-
-        ; no boundary checks. Assuming that D + C < SCREEN_WIDTH
-
-clear_line:
-        ld b, #8            ; 8 pixel lines to clear for this char
-clear_char:
-        ld (de), a
-        inc d
-        djnz clear_char
+       ; Build the video library as the only driver
 
-        ex de, hl
-        inc de
-        push de
-        pop hl
+ZXVID_ONLY     .equ    1
 
-        dec c
-        jr nz, clear_line
-       pop bc
-       pop de
-       call videoattr
-       ld a,(_curattr)
-       ld b,c
-setattr:
-       ld (hl),a
-       inc hl
-       djnz setattr
-        ret
-
-copy_line:
-        ; HL - source, DE - destination
-
-        ; convert line coordinates to screen coordinates both for DE and HL
-        push de
-        ex de, hl
-        call videopos
-        ex de, hl
-        pop de
-        call videopos
-
-        ld c, #8
-
-copy_line_nextchar:
-        push hl
-        push de
-
-        ld b, #32
-
-copy_pixel_line:
-        ld a, (hl)
-        ld (de), a
-        inc e
-        inc l
-        djnz copy_pixel_line
-
-        pop de
-        pop hl
-        inc d
-        inc h
-        dec c
-        jr nz, copy_line_nextchar
-        ret
-
-        ; TODO: the LDIR way should be much faster
-
-_scroll_down:
-        ; set HL = (0,22), DE = (0, 23)
-        xor a
-        ld d, a
-        ld h, a
-        ld l, #22
-        ld e, #23
-        ld c, #23           ; 23 lines to move
-
-loop_scroll_down:
-        push hl
-        push de
-        push bc
-
-        call copy_line
-
-        pop bc
-        pop de
-        pop hl
-
-        dec l
-        dec e
-        dec c
-        jr nz, loop_scroll_down
-
-       ; Attributes
-       ld hl,#0x5ADF
-       ld de,#0x5AFF
-       ld bc,#0x02E0
-       lddr
-
-        ret
-
-
-_scroll_up:
-        ; set HL = (0,1), DE = (0, 0)
-        xor a
-        ld d, a
-        ld e, a
-        ld h, a
-        ld l, #1
-        ld c, #23           ; 23 lines to move
-
-loop_scroll_up:
-        push hl
-        push de
-        push bc
-
-        call copy_line
-
-        pop bc
-        pop de
-        pop hl
-
-        inc l
-        inc e
-        dec c
-        jr nz, loop_scroll_up
-
-       ld hl,#0x5820
-       ld de,#0x5800
-       ld bc,#0x02E0
-       ldir
-        ret
-
-_cursor_on:
-       pop bc
-        pop hl
-        pop de
-        push de
-        push hl
-       push bc
-        ld (cursorpos), de
-
-        call videopos
-        ld a, #7
-        add a, d
-        ld d, a
-        ld a, #0xFF
-        ld (de), a
-        ret
-_cursor_disable:
-_cursor_off:
-        ld de, (cursorpos)
-        call videopos
-        ld a, #7
-        add a, d
-        ld d, a
-        xor a
-        ld (de), a
-
-_do_beep:
-        ret
+        .area _VIDEO
 
-        .area _DATA
+       .include "../dev/zx/video.s"
 
-cursorpos:
-        .dw 0