Menu

#1987 With real C128 hardware Z80 cannot access Char ROM

v3.x
closed-fixed
None
x128
2024-04-27
2024-02-11
No

Apparently with Z80 the character ROM at addresses $d000-$dfff is not accessible. With real hardware, what is seen by the Z80 CPU, is RAM at these addresses, even if MMU is configured to ROM $d000-$dfff (CR bit 0). Using Bank 2 made no difference - the Z80 again saw RAM at $d000-$dfff.

This is not currently emulated accurately - x128 and Z64K both see ROM at these addresses.

The following test programs copy from MMU bank 0/2 ROM configuration the $d000-$dfff addresses to $3000-$3fff. The emulators copy the Char ROM. But as said, it does not work on real hardware.

main    .org   $1c01
    .byte $0c,$08,$0a,$00,$9e,$37,$31,$38,$31,$00,$00,$00
    lda #$3e
    sta $ff00   ;select RAM config
    sei     ;disable interrupts
    lda #$00    ;disable 2 Mhz
    sta $d030
    lda #$c3
    sta $ffee   ;store JP instruction for Z80 mode start
    lda #<z80code
    sta $ffef   ;store lo-byte address of Z80 code
    lda #>z80code
    sta $fff0   ;store hi-byte address of Z80 code
    lda #$b0
    sta $d505   ;activate Z80
    nop
    lda #$cf    ;restore Z80 RST
    sta $ffee
    lda #$00
    sta $ff00
    cli
    rts

z80code     
    .byte $f3       ;di
    .byte $3e $01       ;ld a,01h - bank configuration with char ROM, change to 'ld a,81h' to use Bank 2
    .byte $32 $00 $ff   ;ld (ff00h),a
    .byte $01 $00 $10   ;ld bc,1000h
    .byte $11 $00 $30   ;ld de,3000h
    .byte $21 $00 $d0   ;ld hl,d000h
    .byte $ed $b0       ;ldir
    .byte $3e $3e       ;ld a,3eh - bank to RAM
    .byte $32 $00 $ff   ;ld (ff00h),a
    .byte $c3 $e0 $ff   ;JP ffe6h - give control back to 8502
endcode
2 Attachments

Discussion

  • Jussi Ala-Könni

    A test indicated that Char-ROM is accessible to Z80 in C64 mode, but memory management is very different in C64 mode. The inaccessibility of Char-ROM in C128 mode seems to be related to the Z80 BIOS relocation $d000-$dfff >$0000-$0fff. And since the Z80 BIOS is not present in C64 mode, the accessibility of Char-ROM in C64 mode seems understandable.

    It is no solution of course, since C64 mode cannot be returned from by program means.

     
  • Jussi Ala-Könni

    I have a test program for this case.

        ;Z80D000test written by Jussi Ala-Könni
        ;This program whether RAM, character ROM (or possibly I/O) is accessible
        ;by Z80 at address $D000 with MMU all-ROM configuration (RAM banks 0-3).
        ;The proper result (that of real C128) is that RAM is accessible.
        ;Test result is output to the debug register and screen border color
        ;(green = pass, red = fail).
        ;Compiled using win2c64 by Aart J.C. Bik
    
    main    .org   $1c01
        .byte $0c,$08,$0a,$00,$9e,$37,$31,$38,$31,$00,$00,$00
    
        lda #$00    ;disable 2 Mhz
        sta $d030
        sei
        lda #$06    ;set 8 kb common RAM bottom
        sta $d506
        ldy #$01    ;select configuration with Char ROM
        sty $ff00
        lda $d000   ;load the first byte of Char ROM
        sta $1ff0   ;store value to memory
        eor #$ff    ;flip bits
        ldy #$7f    ;select BANK 1 with RAM
        sty $ff00
        sta $d000   ;store value there
        ldy #$3f    ;select BANK 0 with RAM
        sty $ff00
        sta $d000   ;store value there
        ldy #$3e    ;select RAM config with I/0
        sty $ff00
        eor #$f0    ;store half-EORred value
        sta $d000   ;to VIC register (sprite 0 x-coordinate)
        lda #$c3
        sta $ffee   ;store JP instruction for Z80 mode start
        lda #<z80code
        sta $ffef   ;store lo-byte address of Z80 code
        lda #>z80code
        sta $fff0   ;store hi-byte address of Z80 code
        lda #$b0
        sta $d505   ;activate Z80
        nop
        lda #$cf    ;restore Z80 RST
        sta $ffee
        lda #$04    ;restore 1kb common RAM
        sta $d506
        lda #$00    ;set ROM configuration
        sta $ff00
        cli
        ldx #$00    ;index 0 = RAM Bank 0
        jsr _compare    ;compare
        sty $1ff8   ;store result to memory
        inx     ;index 1 = RAM Bank 1
        jsr _compare    ;compare
        sty $1ff9   ;store result to memory
        inx     ;index 2 = RAM Bank 2
        jsr _compare    ;compare
        sty $1ffa   ;store result to memory
        inx     ;index 3 = RAM Bank 3
        jsr _compare    ;compare
        sty $1ffb   ;store result to memory
        tya     ;combine flags
        ora $1ff8   ;1, 2, or 4 is a clear result
        ora $1ff9   ;everything else is erroneous
        ora $1ffa
        pha
        jsr _display_result
        pla
        ldx #$02    ;2 = fails
        ldy #$ff    ;ff = fails
        cmp #$04    ;correct result is if Z80 saw RAM
        bne _skip   ;everything else is erroneous
        ldx #$05    ;5 = passes
        ldy #$00    ;00 = passes
    _skip:  stx $d020   ;output border colour
        sty $d7ff   ;output to debug register
        rts
    
    _compare:
        ldy #$80    ;flag $80 = no clear result
        lda $1ff0   ;load ROM byte
        cmp $1ff1,x ;compare ROM byte to the byte read by Z80
        bne _skip1  ;skip if not in agreement
        ldy #$01    ;agrees > 1 = Z80 saw ROM
        rts
    _skip1: eor #$0f    ;half-EORed byte was stored to VIC sprite X-coordinate
        cmp $1ff1,x ;does it agree with byte read by Z80?
        bne _skip2  ;no, skip
        ldy #$02    ;agrees > 2 = Z80 saw I/O
        rts
    _skip2: eor #$f0    ;full EORed byte was stored to Bank 0 and Bank 1 RAM
        cmp $1ff1,x ;does it agree with byte read by Z80?
        bne _skip3  ;no, skip
        ldy #$04    ;agrees > 4 = Z80 saw RAM
    _skip3: rts
    
    _display_result
        cmp #$01    ;flag = 1
        beq _seesrom
        cmp #$02    ;flag = 2
        beq _seesio
        cmp #$04    ;flag = 4
        beq _seesram
        jsr $ff7d   ;everything else means unclear result
        .byte 'SOMETHING IS VERY WRONG.',$0d,$00
        rts
    _seesram:
        jsr $ff7d
        .byte 'Z80 SEES RAM AT $D000',$0d,$00
        rts
    _seesio:
        jsr $ff7d
        .byte 'Z80 SEES I/O AT $D000',$0d,$00
        rts
    _seesrom:
        jsr $ff7d
        .byte 'Z80 SEES ROM AT $D000',$0d,$00
        rts
    
    z80code     
        .byte $f3,$21,$00,$d0,$dd,$21,$f0,$1f,$fd,$21,$00,$ff,$fd,$36,$00,$01
        .byte $7e,$dd,$77,$01,$fd,$36,$00,$41,$7e,$dd,$77,$02,$fd,$36,$00,$81
        .byte $7e,$dd,$77,$03,$fd,$36,$00,$c1,$7e,$dd,$77,$04,$fd,$36,$00,$3e
        .byte $c3,$e6,$ff
    
    ;   di
    ;   ld  hl,0d000h ;load address
    ;   ld  ix,01ff0h ;store address
    ;   ld  iy,0ff00h ;MMU CR address
    ;   ld  (iy+0),01h ;ROM and RAM bank 0
    ;   ld  a,(hl)
    ;   ld  (ix+1),a            
    ;   ld  (iy+0),41h ;ROM and RAM bank 1
    ;   ld  a,(hl)
    ;   ld  (ix+2),a            
    ;   ld  (iy+0),81h ;ROM and RAM bank 2
    ;   ld  a,(hl)
    ;   ld  (ix+3),a            
    ;   ld  (iy+0),0c1h ;ROM and RAM bank 3
    ;   ld  a,(hl)
    ;   ld  (ix+4),a            
    ;   ld  (iy+0),03eh ;normal RAM configuration with I/O
    ;   jp  0ffe6h ;give control back to 8502
    
    ;   after execution, results can be peeked at $1ff0-$1ffb
    ;   $1ff0: ROM byte
    ;   $1ff1-$1ff4: Z80 bytes from $d000, banks 1, 2, 3, 4
    ;   $1ff8-$1ffb: comparison flags for banks 1, 2, 3, 4
    
    endcode
    

    2024-02-22: changed flag initial value.

     

    Last edit: Jussi Ala-Könni 2024-02-21
  • Roberto Muscedere

    • assigned_to: Roberto Muscedere
     
  • Roberto Muscedere

    Okay fixed this, but before I commit, can you do a test for c64 mode? The only difference is you can't go back to c128 mode, but you can write something to the screen ram to say if it passed or not. We won't be able to use the debug cart, but it will be something anyways.

     
  • Jussi Ala-Könni

    I already had one at hand, attached.

     
  • Roberto Muscedere

    Fixed in r45099. Also, please incorporate this into your testing suite. I think we can do some automation with the c64 one by comparing screen captures.

     
    • Jussi Ala-Könni

      r45099 is delayed.

       
  • Roberto Muscedere

    • status: open --> pending-fixed
     
  • Jussi Ala-Könni

    This now works as real hardware. Attached is a small test program, which copies $d000-$dfff to $4000-$4fff. Incorrectly it came from Char ROM, but on real hardware it comes from Bank 0 RAM.

        .org    1bffh
    
        .byte 01h,1ch,0ch,08h,0ah,00h,9eh,37h,31h,38h,31h,00h,00h,00h,78h,0a9h
        .byte 0beh,8dh,00h,0ffh,0a9h,00h,8dh,30h,0d0h,0a9h,0c3h,8dh,0eeh,0ffh,0a9h
        .byte z80code&00ffh
        .byte 8dh,0efh,0ffh,0a9h
        .byte z80code>>8
        .byte 8dh,0f0h,0ffh,0a9h,0b0h,8dh,05h,0d5h,0eah,0a9h,0cfh
        .byte 8dh,0eeh,0ffh,0a9h,00h,8dh,00h,0ffh,58h,60h
    
    z80code
        ld a,01h
        ld (0ff00h),a
        ld bc,1000h
        ld hl,0dfffh
        ld de,4fffh
        lddr
        ld a,3eh
        ld (0ff00h),a
        jp 0ffe6h
    
        .end
    

    By altering bytes at $1c42-$1c43 the starting address ($dfff, downwards) can be changed, and easily verified that z80 sees other ROM banks, but not Char ROM at $d000-$dfff.

     
  • Roberto Muscedere

    Please add this to your suite of tests. Ideally they should have the debugcart functionality. At some point, we will combine them into a single test suite.

     
  • Roberto Muscedere

    • status: pending-fixed --> closed-fixed
     
  • Jussi Ala-Könni

    The test I wrote (listed above) already has the debugcart functionality.

     

Log in to post a comment.