Wednesday, August 15, 2018

--> Z80

Once the Z80 came out, the 8080 was pretty much doomed in the personal computer market.
It may add additional instructions and registers vs the 8080, but the number of special cases where instructions only work on certain registers still makes the code a bit larger than it should be.
The 4 bit ALU makes it kinda slow per clock cycle, but since it doesn't have to access RAM every cycle, you could get away with running it faster on the same speed RAM.
This code is very different than the VZ version, and the changes were thrown together in an hour. 
Bugs are quite possible.
<edit>
The code that writes to the screen can be sped up.

;**************************************************
; write two characters at once
;**************************************************
print642:
  ; C contains left character, A contains right character
  ld  h,0    ; clear h
  ld  l,c    ; now HL = left char
  ld  d,h    ; clear d
  ld  e,a    ; now DE = right char
  ld  bc,FONT_ADDRl-224 ;add font address  - correct for missing  sbc a,' '
  ; Calculate location of the first character
  add  hl,hl   ; now HL = 2 *  INT(char)
  add  hl,hl   ; now HL = 4 *  INT(char)
  add  hl,hl   ; now HL = 8 *  INT(char)
  add  hl,bc   ; now hl = FONT_ADDR + 8 *  INT(char)
  ex  de,hl   ; use DE for first character data pointer, now HL = right char
  
  ; Calculate location of the second character
  add  hl,hl   ; now HL = 2 *  INT(char)
  add  hl,hl   ; now HL = 4 *  INT(char)
  add  hl,hl   ; now HL = 8 *  INT(char)
  add  hl,bc   ; now hl = FONT_ADDR + 7 *  INT(char)  HL is now 2nd character data pointer

  ; now calculate screen address
  ld  a,(AT_IROW)  ; get the row
  adc  a,70h   ; add screen MSB
  ld  ixh,a   ; save it
  ld  a,(AT_COL)  ; get the column
  rra      ; least significant bit only indicates which half of byte character is on
  ld  ixl,a   ; screen address LSB is 0 so just put a in l

  ;start printing
  ld  a,(de)   ; get byte of 1st char
  add  a,(hl)   ; get byte of 2nd char
  ld  (IX+0),a  ; write result back to screen
  inc  de    ; next font1 data location
  inc  hl    ; next font2 data location

  ld  a,(de)   ; get byte of 1st char
  add  a,(hl)   ; get byte of 2nd char
  ld  (IX+1),a  ; write result back to screen
  inc  de    ; next font1 data location
  inc  hl    ; next font2 data location

  ld  a,(de)   ; get byte of 1st char
  add  a,(hl)   ; get byte of 2nd char
  ld  (IX+2),a  ; write result back to screen
  inc  de    ; next font1 data location
  inc  hl    ; next font2 data location

  ld  a,(de)   ; get byte of 1st char
  add  a,(hl)   ; get byte of 2nd char
  ld  (IX+3),a  ; write result back to screen
  inc  de    ; next font1 data location
  inc  hl    ; next font2 data location

  ld  a,(de)   ; get byte of 1st char
  add  a,(hl)   ; get byte of 2nd char
  ld  (IX+4),a  ; write result back to screen
  inc  de    ; next font1 data location
  inc  hl    ; next font2 data location

  ld  a,(de)   ; get byte of 1st char
  add  a,(hl)   ; get byte of 2nd char
  ld  (IX+5),a  ; write result back to screen
  inc  de    ; next font1 data location
  inc  hl    ; next font2 data location

  ld  a,(de)   ; get byte of 1st char
  add  a,(hl)   ; get byte of 2nd char
  ld  (IX+6),a  ; write result back to screen
  inc  de    ; next font1 data location
  inc  hl    ; next font2 data location

  ld  a,(de)   ; get byte of 1st char
  add  a,(hl)   ; get byte of 2nd char
  ld  (IX+7),a  ; write result back to screen

  ret

1 comment:

  1. I thought I had aligned the font so I could increment the pointers as bytes instead of 16 bit registers at least 2 years ago.
    That saves 16 clock cycles per pair of characters, and for an entire screen, that adds up to 32 x 24 x 8 clock cycles per screen.
    That's 6144 clock cycles per screen.

    ReplyDelete