From 3edb9592981c6cbcdfffafdf4799d2ae82fe3690 Mon Sep 17 00:00:00 2001
From: Oliver Schmidt
Date: Thu, 13 Mar 2025 21:31:01 +0100
Subject: [PATCH] Finally made CONIO and STDIO fully interoperable in 80 column
mode.
In order to avoid undefined behaviour of programs not aware of 80 column mode, the 80 column firmware deliberately doesn't use CH but OURCH. So in order to be fully interoperable, CONIO needs to do the same. This changes introduces that behavior. So far so good.
But the 80 column firmware can also be active in 40 column mode. This scenario is not detectable with reasonable effort. Therefore the behaviour of CONIO in this scenario is _not_ improved. However, this scenario is supposed to be very uncommon - and a recent update to videomode() makes sure to not activate it anymore ourselves.
Notes:
* If a program wants to be 100% sure to not run in 40 column mode with 80 column firmware active it can call videomode(VIDEOMODE_40COL) to explicitly deactivate a potentially active 80 column firmware. However, this always implicitly clears the screen.
* In 40 column mode (contrast to 80 column mode) the 80 column firmware updates CH to reflect OURCH. So as long as CONIO only reads CH, but doesn't update it, everything works as expected. Interestingly this makes a rather useful scenario of STDIO/CONIO interoperation work: Using STDIO for screen output and CONIO for keyboard input. When cgetc() is called after cursor(1), it has to write to the screen as there's no hardware cursor on the Apple II. Those writes work as expected even in 40 column mode with active 80 column firmware as CH is only read but not written.
---
asminc/apple2.inc | 6 ++++++
libsrc/apple2/beep.s | 12 ++++++------
libsrc/apple2/bell.s | 20 --------------------
libsrc/apple2/cpeekc.s | 2 +-
libsrc/apple2/cputc.s | 27 ++++++++++++++++++---------
libsrc/apple2/gotoxy.s | 5 +++++
libsrc/apple2/wherex.s | 7 ++++++-
7 files changed, 42 insertions(+), 37 deletions(-)
delete mode 100644 libsrc/apple2/bell.s
diff --git a/asminc/apple2.inc b/asminc/apple2.inc
index 528c463a1..fb4a1b2f0 100644
--- a/asminc/apple2.inc
+++ b/asminc/apple2.inc
@@ -25,6 +25,12 @@ BRKVec := $03F0 ; Break vector
SOFTEV := $03F2 ; Vector for warm start
PWREDUP := $03F4 ; This must be = EOR #$A5 of SOFTEV+1
+;-----------------------------------------------------------------------------
+; 80 column firmware
+
+OURCH := $057B ; Cursor horizontal position
+OURCV := $05FB ; Cursor vertical position
+
;-----------------------------------------------------------------------------
; Hardware
diff --git a/libsrc/apple2/beep.s b/libsrc/apple2/beep.s
index ebebb6e3f..84d132a3a 100644
--- a/libsrc/apple2/beep.s
+++ b/libsrc/apple2/beep.s
@@ -5,16 +5,16 @@
;
.export _beep
- .import BELL
.include "apple2.inc"
.segment "LOWCODE"
_beep:
- lda CH ; Bell scrambles CH in 80col mode on IIgs, storing
- pha ; it in OURCH and resetting CH to 0. Save it.
- jsr BELL
- pla
- sta CH ; Restore CH
+ ; Switch in ROM and call BELL
+ bit $C082
+ jsr $FF3A ; BELL
+
+ ; Switch in LC bank 2 for R/O and return
+ bit $C080
rts
diff --git a/libsrc/apple2/bell.s b/libsrc/apple2/bell.s
deleted file mode 100644
index 28e6d24f8..000000000
--- a/libsrc/apple2/bell.s
+++ /dev/null
@@ -1,20 +0,0 @@
-;
-; Colin Leroy-Mira, 2024
-;
-; BELL routine
-;
-
- .export BELL
-
- .include "apple2.inc"
-
- .segment "LOWCODE"
-
-BELL:
- ; Switch in ROM and call BELL
- bit $C082
- jsr $FF3A ; BELL
-
- ; Switch in LC bank 2 for R/O and return
- bit $C080
- rts
diff --git a/libsrc/apple2/cpeekc.s b/libsrc/apple2/cpeekc.s
index 200206177..a6a082eab 100644
--- a/libsrc/apple2/cpeekc.s
+++ b/libsrc/apple2/cpeekc.s
@@ -14,7 +14,7 @@ _cpeekc:
sec ; Assume main memory
bit RD80VID ; In 80 column mode?
bpl peek ; No, just go ahead
- tya
+ lda OURCH
lsr ; Div by 2
tay
bcs peek ; Odd cols are in main memory
diff --git a/libsrc/apple2/cputc.s b/libsrc/apple2/cputc.s
index 2dcfa1e00..f60965f44 100644
--- a/libsrc/apple2/cputc.s
+++ b/libsrc/apple2/cputc.s
@@ -52,19 +52,29 @@ _cputc:
cputdirect:
jsr putchar
+ .ifdef __APPLE2ENH__
+ bit RD80VID ; In 80 column mode?
+ bpl :+
+ inc OURCH ; Bump to next column
+ lda OURCH
+ bra check ; Must leave CH alone
+: .endif
inc CH ; Bump to next column
lda CH
- cmp WNDWDTH
- bcc :+
+check: cmp WNDWDTH
+ bcc done
jsr newline
left:
- .if (.cpu .bitand CPU_ISET_65SC02)
+ .ifdef __APPLE2ENH__
stz CH ; Goto left edge of screen
+ bit RD80VID ; In 80 column mode?
+ bpl done
+ stz OURCH ; Goto left edge of screen
.else
lda #$00 ; Goto left edge of screen
sta CH
.endif
-: rts
+done: rts
newline:
inc CV ; Bump to next line
@@ -89,21 +99,20 @@ mask: and INVFLG ; Apply normal, inverse, flash
putchardirect:
tax
+ ldy CH
.ifdef __APPLE2ENH__
- lda CH
sec ; Assume main memory
bit RD80VID ; In 80 column mode?
bpl put ; No, just go ahead
+ lda OURCH
lsr ; Div by 2
+ tay
bcs put ; Odd cols go in main memory
php
sei ; No valid MSLOT et al. in aux memory
bit HISCR ; Assume SET80COL
-put: tay
- .else
- ldy CH
.endif
- lda (BASL),Y ; Get current character
+put: lda (BASL),Y ; Get current character
sta tmp3 ; Save old character for _cgetc
txa
sta (BASL),Y
diff --git a/libsrc/apple2/gotoxy.s b/libsrc/apple2/gotoxy.s
index 6755af8d8..2a0261eba 100644
--- a/libsrc/apple2/gotoxy.s
+++ b/libsrc/apple2/gotoxy.s
@@ -22,4 +22,9 @@ _gotoxy:
_gotox:
sta CH ; Store X
+ .ifdef __APPLE2ENH__
+ bit RD80VID ; In 80 column mode?
+ bpl :+
+ sta OURCH ; Store X
+: .endif
rts
diff --git a/libsrc/apple2/wherex.s b/libsrc/apple2/wherex.s
index bd717a22b..4d4f856f0 100644
--- a/libsrc/apple2/wherex.s
+++ b/libsrc/apple2/wherex.s
@@ -10,5 +10,10 @@
_wherex:
lda CH
- ldx #$00
+ .ifdef __APPLE2ENH__
+ bit RD80VID ; In 80 column mode?
+ bpl :+
+ lda OURCH
+: .endif
+ ldx #>$0000
rts