msx1: sketch out the bits needed to work the brain dead slot system
authorAlan Cox <alan@etchedpixels.co.uk>
Fri, 7 Nov 2014 00:49:29 +0000 (00:49 +0000)
committerAlan Cox <alan@etchedpixels.co.uk>
Fri, 7 Nov 2014 00:49:29 +0000 (00:49 +0000)
Plus find the megarams.

All untested.

Kernel/platform-msx1/crt0.s
Kernel/platform-msx1/msx1.s

index 1765f36..ec77a1d 100644 (file)
@@ -9,6 +9,8 @@
                .area _CONST
                .area _DISCARD
                .area _DATA
+               ; Must be over 0x8000 for HIGHCODE
+               .area _HIGHCODE
                .area _INITIALIZED
                .area _BSEG
                .area _BSS
index d6a4d79..4dc51df 100644 (file)
@@ -221,3 +221,297 @@ outchar:
            pop af
             ret
 
+;
+;      On entry D is repeating slot pattern, E repeating SSLOT pattern
+;
+;
+;      We play with 0x0000-0x7FFF (for user mappings) and with
+;      0xC000-0xFFFF (for the stupid sslot stuff), so this wants to live
+;      in 0x8000-0xBFFF. We must also be very careful with our sslot
+;      read/writes as while we do the sslot jiggery-pokery we have unmapped
+;      our stack.
+;
+;
+           .area _HIGHCODE
+setslot0:
+           push bc
+           in a, (0xA8)
+           and #0xFC
+           ld b, a
+           ld a, d
+           and #0x03
+           or b
+           ld b, a             ; Final mapping
+           in a, (0xA8)
+           and #0x3C
+           ld c, a
+           ld a, d
+           and #0xC3
+           or c
+           ld c, a             ; Temporary mapping for SSLOT crap
+           out (0xA8), a
+           ld a, e
+           and #0x03
+           ld e, a
+           ld a, (0xFFFF)
+           cpl
+           and #0xFC
+           or e
+           ld (0xFFFF), a      ; Set SSLOT
+           ld a, b             ; Final PSLOT (unmap the SSLOT)
+           out (0xA8), a
+           pop bc
+           ret
+
+;
+;      This can't live low as its used by _HIGHCODE stuff
+;
+
+setslot1:
+           push bc
+           in a, (0xA8)
+           and #0xF3
+           ld b, a
+           ld a, d
+           and #0x0C
+           or b
+           ld b, a             ; Final mapping
+           in a, (0xA8)
+           and #0x33
+           ld c, a
+           ld a, d
+           and #0xCC
+           or c
+           ld c, a             ; Temporary mapping for SSLOT crap
+           out (0xA8), a
+           ld a, e
+           and #0x0C
+           ld e, a
+           ld a, (0xFFFF)
+           cpl
+           and #0xF3
+           or e
+           ld (0xFFFF), a      ; Set SSLOT
+           ld a, b             ; Final PSLOT (unmap the SSLOT)
+           out (0xA8), a
+           pop bc
+           ret
+
+;
+;      Sufficient ?? FIXME - maybe wrong approach anyway
+;
+saveslotmap:
+           in a, (0xA8)
+           ld (slot), a        ; Slots
+           ld a, (0xFFFF)
+           cpl
+           ld (slots), a
+           ret
+
+restoreslotmap:
+           ld a, (slot)
+           out (0xA8), a
+           ld a, (slots)
+           ld (0xFFFF), a
+           ret
+
+;
+;      Can't be in common as we bugger about with 0xC000+
+;
+           .area _HIGHCODE
+
+systemslotmap:
+           in a, (0xA8)
+           ld (system_pslot), a
+           ld d, a             ; need this in a register
+           and #0x3F           ; all but top 16K
+           ld e, a
+           and #3              ; Low 16K
+           rrca                ; Into the top 16K space
+           rrca
+           or e
+           ld (system_pslot0), a
+           out (0xA8), a
+           ld a, (0xFFFF)
+           ld a, d
+           out (0xA8), a       ; Put things back to sanity
+           cpl
+           ld (system_sslot0), a
+           ld a, d
+           and #0x3F
+           ld e, a
+           and #0x0C
+           rlca
+           rlca
+           rlca
+           rlca
+           or e
+           ld (system_pslot1), a
+           out (0xA8), a
+           ld a, (0xFFFF)
+           ld a, d
+           out (0xA8), a
+           cpl
+           ld (system_sslot1), a
+           ret
+
+system_pslot0: .db 0           ; Keep paired..
+system_sslot0: .db 0
+system_pslot1: .db 0
+system_sslot1: .db 0
+system_pslot:  .db 0
+
+;
+;      Map the system as we recorded it in systemslotmap
+;
+;      Must reside below 0xC000
+;
+map_system:
+           ld c, #0xA8
+           in b, (c)
+           ld de, (system_pslot0)      ; e=pslot0, d=sslot0
+           out (c), e
+           ld a, d
+           ld (0xFFFF), a
+           out (c), b
+           ld de, (system_pslot1)      ; e=pslot1, d=sslot1
+           out (c), e
+           ld a, d
+           ld (0xFFFF), a
+           out (c), b
+           ld a, (system_pslot)
+           out (c), a
+           ret
+
+slotexpanded:
+           push hl
+           ld hl, #0xFFFF
+           ld a, (hl)          ; Read cpl value
+           cpl                 ; A is now the write value
+           ld (hl), a          ; Write it
+           cpl
+           cp (hl)
+           pop hl
+           ret                 ; Z = Expanded
+
+slot:      .db 0
+slots:     .db 0
+
+;
+;      Scan slot 1 for all the slots and subslots. For each slot/sub
+;      call hl' with the registers exchanged for the scanner routines
+;      use
+;
+slotscan1:
+           call saveslotmap
+
+           ld d, #0
+nextslot:
+           ld e, #0
+nextexpanded:
+           call setslot1
+           exx
+           call callhl         ; Scan
+           exx
+           call slotexpanded
+           jr nz, noexpanded
+           ld a, #0x55
+           add e
+           ld e, a
+           jr nc, nextexpanded
+noexpanded:
+           inc e
+           bit 2, e
+           jr z, nextslot
+           call restoreslotmap
+           ret
+
+callhl:            jp (hl)
+
+megaset0:   xor a
+megaset:    out (c), a         ; ROM mode
+           ld (0x5fff), a      ; page A
+           in a, (c)
+           ret
+;
+;      Hunt for a MegaRAM (assumes c set correctly by caller)
+;
+megaram_p:   call megaset0
+           ld a, b             ; Just using d for check code
+           ld (0x5FFF), a      ; Now should store this either way
+           call megaset0
+           ld a, (0x5FFF)
+           cp b                ; Z = MegaRAM (probably)
+           ret
+
+megaram_chk:
+           ld bc, #0xA58E
+           call megaram_p
+           ret nz              ; Not MegaRAM
+           ld c, #0x5A
+           call megaram_p      ; Paranoia check
+           ret
+
+megaram_scan_f:
+           call megaram_chk
+           ret nz
+           exx
+           ld (megaram_i), de  ; save de' (slot/subslot info)
+           exx
+           ret
+megaram_i:  .dw 0
+
+megaram_scan:
+           exx
+           ld hl, #megaram_scan_f
+           exx
+           call slotscan1
+           ld de, (megaram_i)
+           ld a, d
+           or e
+           jr z, megaram_no
+           call setslot1       ; select the megaram
+           ld bc, #0x8E
+           ld hl, #0x5fff
+           call megaset0
+           ld (hl), #0x55
+megaram_size:
+           ld a, b
+           call megaset
+           ld a, (hl)
+           cp #0x55
+           jr z, megawrap_maybe
+megaram_size2:
+           inc b
+           jr nz, megaram_size
+megaram_sized:
+           call restoreslotmap
+           ; b is the size in 8K pages
+            ld a, b
+           rra
+           rra
+           and #0x3F
+           ret nz
+           add #0x40
+           ret
+megaram_no:
+           xor a
+           ret
+
+megawrap_maybe:
+           call megaset0
+           ld (hl), #0xAA
+           ld a, b
+           call megaset
+           ld a, (hl)
+           cp #0xAA            ; both patterns worked
+           jr z, megaram_sized
+           jr megaram_size2    ; false alarm, carry on
+
+map_megaram:
+           ld de, (megaram_i)
+           push de
+           call setslot0
+           pop de
+           call setslot1
+           ret