Skip to content

Commit

Permalink
Merge pull request #39 from markadev/abaffa-videx-compatibility-mode
Browse files Browse the repository at this point in the history
Integrate in "Videx compatibility" from abaffa's changes
  • Loading branch information
markadev authored Mar 10, 2024
2 parents 3d719ca + f812c5a commit 17d1fd8
Show file tree
Hide file tree
Showing 26 changed files with 25,992 additions and 79 deletions.
19 changes: 17 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ These features are currently supported:
(thanks to @dkgrizzly and @Paco1979)
* Soft-monochrome mode to force display as if on a monochrome monitor
* Some Video-7 RGB card extended graphical modes are implemented
* Compatibility with Videx VideoTerm modes on Apple II+ (thanks to @abaffa)

I had these goals in mind during design:
* Generate video out to a more modern display - I don't have any old CRTs for
Expand Down Expand Up @@ -94,8 +95,22 @@ a cheap composite -> HDMI adapter
**DHires**
![DHires Mode](docs/composite_vs_vga_dhires.jpg)

**80 Columms**
![80 Columms Mode](docs/composite_vs_vga_80columms.jpg)
**80 Columns**
![80 Columns Mode](docs/composite_vs_vga_80columms.jpg)


## 80 Column support for the Apple II+

The firmware implements Videx VideoTerm compatibility when there's a VideoTerm card installed
in slot 3. It's not enabled by default but if you have a Videx VideoTerm card in slot 3
then you can enable 80 column VGA support using the Configuration Disk image. The VGA card
can still be installed in any slot.

**Apple II+ running 80 Columns Examples**

![AppleII 80 Columms Mode 1](docs/apple2plus_videx_80columns1.jpg)
![AppleII 80 Columms Mode 2](docs/apple2plus_videx_80columns2.jpg)
![AppleII 80 Columms Mode 3](docs/apple2plus_videx_80columns3.jpg)


## Future work
Expand Down
27 changes: 18 additions & 9 deletions config-disk/STARTUP.bas
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,11 @@
130 PRINT "1 SCANLINES ON 2 SCANLINES OFF"
140 PRINT "3 MONOCHROME ON 4 MONOCHROME OFF"
150 PRINT "5 MONOCHROME CFG 6 CHARSET CFG"
170 PRINT "7 COLOR PATTERNS": PRINT ""
180 PRINT "11 ABOUT": PRINT "12 LOAD DEFAULT CONFIG"
180 PRINT "13 QUIT W/OUT SAVING": PRINT"14 SAVE AND QUIT": PRINT ""
160 PRINT "7 ][+ VIDEX ON 8 ][+ VIDEX OFF"
170 PRINT "9 COLOR PATTERNS": PRINT ""
175 PRINT "11 ABOUT"
180 PRINT "12 LOAD DEFAULT CONFIG": PRINT "13 LOAD SAVED CONFIG"
185 PRINT "14 SAVE AND QUIT": PRINT "15 QUIT W/OUT SAVING"
190 VTAB 22: GOSUB 1400: INPUT "PLEASE ENTER YOUR SELECTION: ";CH
200 IF CH < 1 THEN GOSUB 1550
210 IF CH = 1 THEN GOSUB 500
Expand All @@ -23,14 +25,15 @@
240 IF CH = 4 THEN GOSUB 650
250 IF CH = 5 THEN GOSUB 2000
260 IF CH = 6 THEN GOSUB 3000
270 IF CH = 7 THEN GOSUB 700
280 IF CH = 8 THEN GOSUB 1550
290 IF CH = 9 THEN GOSUB 1550
270 IF CH = 7 THEN GOSUB 900
280 IF CH = 8 THEN GOSUB 950
290 IF CH = 9 THEN GOSUB 700
300 IF CH = 10 THEN GOSUB 1550
310 IF CH = 11 THEN GOSUB 1650
320 IF CH = 12 THEN GOSUB 800
330 IF CH = 13 THEN GOTO 4050
340 IF CH = 14 THEN GOTO 4000
325 IF CH = 13 THEN GOSUB 850
330 IF CH = 14 THEN GOTO 4000
340 IF CH = 15 THEN GOTO 4050
350 IF CH > 14 THEN GOSUB 1550
360 GOTO 100
500 REM '''SCANLINES ON
Expand All @@ -46,7 +49,13 @@
720 FOR I = 0 TO 31: COLOR= I / 2: VLIN 0,39 AT I: NEXT I: FOR I = 0 TO 14 STEP 2: PRINT TAB( I * 2 + 1);I;: NEXT I: PRINT : FOR I = 1 TO 15 STEP 2: PRINT TAB( I * 2 + 1);I;: NEXT I
730 PRINT "": GET A$: TEXT : RETURN
800 REM '''LOAD DEFAULT CONFIGURATION
810 POKE BASEADDR + 4,1: RETURN
810 POKE BASEADDR + 4,0: RETURN
850 REM '''LOAD SAVED CONFIGURATION
860 POKE BASEADDR + 4,1: RETURN
900 REM '''][+ VIDEX ON
910 POKE BASEADDR + 0,4: RETURN
950 REM '''][+ VIDEX OFF
910 POKE BASEADDR + 0,8: RETURN
1400 REM STRING ROUTINES
1410 PRINT "---------------------------------------": RETURN
1450 HOME : PRINT "APPLE II VGA": GOSUB 1400: PRINT "COPYRIGHT (C) 2021-2023 MARK AIKENS": PRINT "COPYRIGHT (C) 2022-2023 DAVID KUDER": RETURN
Expand Down
7 changes: 6 additions & 1 deletion docs/Usage.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ After you load on the firmware for your respective Apple II system (II+ or IIe)
the VGA card is generally plug-and-play. Plug it in, power on your Apple II
and that's it.

There are some optional features and other controls that can be changed using the
menu-based Configuration disk or by directly using `POKE` commands.


## Soft Monochrome Mode

Expand Down Expand Up @@ -56,7 +59,9 @@ This register controls enablement of some features of the card

| bit(s) | Description
| ------ | -----------
| 7:2 | reserved
| 7:4 | reserved
| 3 | Setting to 1 will disable Videx VideoTerm support (II+ only)
| 2 | Setting to 1 will enable Videx VideoTerm support (II+ only)
| 1 | Setting to 1 will disable simulated scanline rendering
| 0 | Setting to 1 will enable simulated scanline rendering

Expand Down
Binary file added docs/apple2plus_videx_80columns1.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/apple2plus_videx_80columns2.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/apple2plus_videx_80columns3.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions pico/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ target_sources(applevga PUBLIC
render_text.c
${TEXTFONT_SRC_FILES}
vga.c
videx_vterm.c
)
target_include_directories(applevga PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
target_link_libraries(applevga PUBLIC
Expand Down
53 changes: 49 additions & 4 deletions pico/abus.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@
#include "buffers.h"
#include "colors.h"
#include "device_regs.h"
#ifdef APPLE_MODEL_IIPLUS
#include "videx_vterm.h"
#endif


#if CONFIG_PIN_APPLEBUS_PHI0 != PHI0_GPIO
Expand All @@ -21,7 +24,7 @@ typedef void (*shadow_handler)(bool is_write, uint_fast16_t address, uint_fast8_


static int reset_detect_state = 0;
static shadow_handler softsw_handlers[128];
static shadow_handler softsw_handlers[256];


static void abus_main_setup(PIO pio, uint sm) {
Expand Down Expand Up @@ -159,6 +162,18 @@ static void shadow_softsw_57(bool is_write, uint_fast16_t address, uint_fast8_t
soft_switches |= SOFTSW_HIRES_MODE;
}

static void shadow_softsw_58(bool is_write, uint_fast16_t address, uint_fast8_t data) {
#ifdef APPLE_MODEL_IIPLUS
videx_vterm_80col_enabled = false;
#endif
}

static void shadow_softsw_59(bool is_write, uint_fast16_t address, uint_fast8_t data) {
#ifdef APPLE_MODEL_IIPLUS
videx_vterm_80col_enabled = true;
#endif
}

static void shadow_softsw_5e(bool is_write, uint_fast16_t address, uint_fast8_t data) {
soft_dhires = true;
}
Expand All @@ -181,6 +196,10 @@ void abus_init() {
// Init states
soft_switches = SOFTSW_TEXT_MODE;

#ifdef APPLE_MODEL_IIPLUS
videx_vterm_init();
#endif

// Setup soft-switch handlers for the Apple model
softsw_handlers[0x21] = shadow_softsw_21;
softsw_handlers[0x50] = shadow_softsw_50;
Expand All @@ -191,6 +210,8 @@ void abus_init() {
softsw_handlers[0x55] = shadow_softsw_55;
softsw_handlers[0x56] = shadow_softsw_56;
softsw_handlers[0x57] = shadow_softsw_57;
softsw_handlers[0x58] = shadow_softsw_58;
softsw_handlers[0x59] = shadow_softsw_59;
#ifdef APPLE_MODEL_IIE
softsw_handlers[0x00] = shadow_softsw_00;
softsw_handlers[0x01] = shadow_softsw_01;
Expand All @@ -203,6 +224,12 @@ void abus_init() {
softsw_handlers[0x5e] = shadow_softsw_5e;
softsw_handlers[0x5f] = shadow_softsw_5f;
#endif
#ifdef APPLE_MODEL_IIPLUS
// slot 3 device registers
for(uint i = 0xb0; i < 0xc0; i++) {
softsw_handlers[i] = videx_vterm_shadow_register;
}
#endif

abus_main_setup(CONFIG_ABUS_PIO, ABUS_MAIN_SM);

Expand Down Expand Up @@ -273,13 +300,28 @@ static void shadow_memory(bool is_write, uint_fast16_t address, uint32_t value)
case 0xc000 >> 10:
reset_detect_state = 0;

// Handle shadowing of the soft switches in the range 0xc000 - 0xc07f
if(address < 0xc080) {
shadow_handler h = softsw_handlers[address & 0x7f];
// Handle shadowing of the soft switches and I/O in the range $C000 - $C0FF
if(address < 0xc100) {
shadow_handler h = softsw_handlers[address & 0xff];
if(h) {
h(is_write, address, value & 0xff);
}
}
#ifdef APPLE_MODEL_IIPLUS
else if((address >= 0xc300) && (address < 0xc400)) {
// slot 3 access
videx_vterm_mem_selected = true;
}
#endif
break;

case 0xc800 >> 10:
case 0xcc00 >> 10:
// expansion slot memory space $C800-$CFFF
reset_detect_state = 0;
#ifdef APPLE_MODEL_IIPLUS
videx_vterm_shadow_c8xx(is_write, address, value);
#endif
break;

case 0x0000 >> 10:
Expand All @@ -305,6 +347,9 @@ static void shadow_memory(bool is_write, uint_fast16_t address, uint32_t value)
soft_80store = false;
soft_altcharset = false;
soft_ramwrt = false;
#ifdef APPLE_MODEL_IIPLUS
videx_vterm_80col_enabled = false;
#endif

reset_detect_state = 0;
} else {
Expand Down
25 changes: 25 additions & 0 deletions pico/config.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@
#include "buffers.h"
#include "colors.h"
#include "textfont/textfont.h"
#ifdef APPLE_MODEL_IIPLUS
#include "videx_vterm.h"
#endif


// A block of flash is reserved for storing configuration persistently across power cycles
Expand All @@ -32,11 +35,18 @@ struct config {

// magic word determines if the stored configuration is valid
uint32_t magic_word;

// Add new fields after here. When reading the config use the IS_STORED_IN_CONFIG macro
// to determine if the field you're looking for is actually present in the stored config.

uint8_t videx_vterm_enabled;
};

// This is a compile-time check to ensure the size of the config struct fits within one flash erase sector
typedef char config_struct_size_check[(sizeof(struct config) <= FLASH_SECTOR_SIZE) - 1];

#define IS_STORED_IN_CONFIG(cfg, field) ((offsetof(struct config, field) + sizeof((cfg)->field)) <= (cfg)->size)


extern uint8_t __persistent_data_start[];
static struct config *cfg = (struct config *)__persistent_data_start;
Expand All @@ -54,6 +64,14 @@ void config_load() {
mono_bg_color = cfg->mono_bg_color;
mono_fg_color = cfg->mono_fg_color;
memcpy(character_rom, cfg->character_rom, CHARACTER_ROM_SIZE);

#ifdef APPLE_MODEL_IIPLUS
if(IS_STORED_IN_CONFIG(cfg, videx_vterm_enabled) && cfg->videx_vterm_enabled) {
videx_vterm_enable();
} else {
videx_vterm_disable();
}
#endif
}


Expand All @@ -63,6 +81,9 @@ void config_load_defaults() {
mono_bg_color = mono_bg_colors[1];
mono_fg_color = mono_fg_colors[1];
memcpy(character_rom, default_character_rom, CHARACTER_ROM_SIZE);
#ifdef APPLE_MODEL_IIPLUS
videx_vterm_disable();
#endif
}


Expand All @@ -71,6 +92,7 @@ void config_save() {
const int new_config_size = (sizeof(struct config) + FLASH_PAGE_SIZE - 1) & -FLASH_PAGE_SIZE;
struct config *new_config = malloc(new_config_size);
memset(new_config, 0xff, new_config_size);
memset(new_config, 0, sizeof(struct config));

new_config->size = sizeof(struct config);
new_config->scanline_emulation = soft_scanline_emulation;
Expand All @@ -79,6 +101,9 @@ void config_save() {
new_config->mono_fg_color = mono_fg_color;
memcpy(new_config->character_rom, character_rom, CHARACTER_ROM_SIZE);
new_config->magic_word = MAGIC_WORD_VALUE;
#ifdef APPLE_MODEL_IIPLUS
new_config->videx_vterm_enabled = videx_vterm_enabled;
#endif

const uint32_t flash_offset = (uint32_t)cfg - XIP_BASE;
flash_range_erase(flash_offset, FLASH_SECTOR_SIZE);
Expand Down
11 changes: 10 additions & 1 deletion pico/device_regs.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@
#include "colors.h"
#include "config.h"
#include "textfont/textfont.h"
#ifdef APPLE_MODEL_IIPLUS
#include "videx_vterm.h"
#endif


static unsigned int char_write_offset;
Expand All @@ -18,6 +21,12 @@ void device_write(uint_fast8_t reg, uint_fast8_t data) {
soft_scanline_emulation = true;
if(data & 0x02)
soft_scanline_emulation = false;
#ifdef APPLE_MODEL_IIPLUS
if(data & 0x04)
videx_vterm_enable();
if(data & 0x08)
videx_vterm_disable();
#endif
break;

// soft-monochrome color setting
Expand Down Expand Up @@ -55,7 +64,7 @@ void device_write(uint_fast8_t reg, uint_fast8_t data) {
// command value.
//
// Note: some of these commands could take a long time (relative to 6502 bus cycles) so
// some bus activity may be missed. Other projects like the Analog-V2 delegate this execution
// some bus activity may be missed. Other projects like the V2-Analog delegate this execution
// to the other (VGA) core to avoid this. Maybe do this if the missed bus cycles become a noticable
// issue; I only expect it would happen when some config is being saved, which is not done often.
void execute_device_command(uint_fast8_t cmd) {
Expand Down
21 changes: 18 additions & 3 deletions pico/render.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
#include "render.h"
#include "buffers.h"
#ifdef APPLE_MODEL_IIPLUS
#include "videx_vterm.h"
#endif


void render_init() {
Expand All @@ -8,11 +11,16 @@ void render_init() {


void render_loop() {
while(1) {
#ifdef RENDER_TEST_PATTERN
while(1) {
render_vga_testpattern();
}
#else
while(1) {
update_text_flasher();
#ifdef APPLE_MODEL_IIPLUS
videx_vterm_update_flasher();
#endif

switch(soft_switches & SOFTSW_MODE_MASK) {
case 0:
Expand All @@ -28,9 +36,16 @@ void render_loop() {
render_hires(true);
break;
default:
render_text();
#ifdef APPLE_MODEL_IIPLUS
if(videx_vterm_enabled && videx_vterm_80col_enabled) {
render_videx_text();
} else
#endif
{
render_text();
}
break;
}
#endif
}
#endif
}
Loading

0 comments on commit 17d1fd8

Please sign in to comment.