diff --git a/cfg/osic1p.cfg b/cfg/osic1p.cfg
index 10ce827fd..4771639a6 100644
--- a/cfg/osic1p.cfg
+++ b/cfg/osic1p.cfg
@@ -7,7 +7,7 @@ SYMBOLS {
 }
 MEMORY {
     # for size of ZP see runtime/zeropage.s and c1p/extzp.s
-    ZP:       file = "", define = yes, start = $0002, size = $001A + $0004;
+    ZP:       file = "", define = yes, start = $0002, size = $001A + $0005;
     RAM:      file = %O, define = yes, start = %S, size = __HIMEM__ - __STACKSIZE__ - %S;
 }
 SEGMENTS {
diff --git a/libsrc/osic1p/cgetc.s b/libsrc/osic1p/cgetc.s
index 3c9dd4381..82857f4c6 100644
--- a/libsrc/osic1p/cgetc.s
+++ b/libsrc/osic1p/cgetc.s
@@ -1,6 +1,8 @@
 ;
 ; char cgetc (void);
 ;
+
+        .constructor    initcgetc
         .export         _cgetc
         .import         cursor
 
@@ -8,8 +10,21 @@
         .include        "extzp.inc"
         .include        "zeropage.inc"
 
+; Initialize one-character buffer that is filled by kbhit()
+initcgetc:
+        lda     #$00
+        sta     CHARBUF         ; No character in buffer initially
+        rts
+
 ; Input routine from 65V PROM MONITOR, show cursor if enabled
 _cgetc:
+        lda     CHARBUF         ; character in buffer available?
+        beq     nobuffer
+        tax                     ; save character in X
+        lda     #$00
+        sta     CHARBUF         ; empty buffer
+        jmp     restorex        ; restore X and return
+nobuffer:
         lda     cursor          ; show cursor?
         beq     nocursor
         ldy     CURS_X
@@ -25,7 +40,9 @@ nocursor:
         lda     tmp1            ; fetch saved character
         ldy     CURS_X
         sta     (SCREEN_PTR),y  ; store at cursor position
+
+restorex:
         txa                     ; restore saved character from X
-        ldx     #$00            ; high byte of int return value
 done:
+        ldx     #$00            ; high byte of int return value
         rts
diff --git a/libsrc/osic1p/extzp.inc b/libsrc/osic1p/extzp.inc
index 06498d1a6..5e85e0b74 100644
--- a/libsrc/osic1p/extzp.inc
+++ b/libsrc/osic1p/extzp.inc
@@ -4,4 +4,4 @@
 
 ; ------------------------------------------------------------------------
 
-        .globalzp       CURS_X, CURS_Y, SCREEN_PTR
+        .globalzp       CURS_X, CURS_Y, SCREEN_PTR, CHARBUF
diff --git a/libsrc/osic1p/extzp.s b/libsrc/osic1p/extzp.s
index 7dc8e3a53..b3bdaa0b7 100644
--- a/libsrc/osic1p/extzp.s
+++ b/libsrc/osic1p/extzp.s
@@ -14,6 +14,7 @@
 CURS_X:         .res    1
 CURS_Y:         .res    1
 SCREEN_PTR:     .res    2
+CHARBUF:        .res    1
 
-; size 4
-; Adjust size of this segment in osic1p.cfg if the size changes
+; size 5
+; Adjust size of the ZP segment in osic1p.cfg if the size changes
diff --git a/libsrc/osic1p/kbhit.s b/libsrc/osic1p/kbhit.s
index c064fec47..67f3c86ed 100644
--- a/libsrc/osic1p/kbhit.s
+++ b/libsrc/osic1p/kbhit.s
@@ -19,10 +19,13 @@ scan:
         rol     a               ; Rotate row select to next bit position
         cmp     #$FF            ; Done?
         bne     scan            ; If not, continue
-        ldx     #$00            ; High byte of return is always zero
         lda     #$00            ; Return false
+        tax                     ; High byte of return is also zero
+        sta     CHARBUF         ; No character in buffer
         rts
 keypressed:
+        jsr     INPUTC          ; Get input character in A
+        sta     CHARBUF         ; Save in buffer
         ldx     #$00            ; High byte of return is always zero
         lda     #$01            ; Return true
         rts