Compare commits

...

10 Commits

Author SHA1 Message Date
David Kuder a82b03e631 Timing tweaks 2023-05-04 23:43:57 -04:00
David Kuder 4bff5c15b5 Misc tweaks 2023-05-04 22:48:39 -04:00
David Kuder c8b4ce9631 Move default mono colors initialization so config works 2023-05-04 22:48:18 -04:00
David Kuder 89367bca09 Timing fixes for II+ 2023-05-04 22:47:02 -04:00
David Kuder 83d737c44e Attempts to improve DHGR rendering 2023-05-04 21:02:13 -04:00
David Kuder 685ff4f632 Double lores fixes 2023-05-04 20:56:58 -04:00
David Kuder 910c644cd7 Restore previous color rendering for HiRes mode 2023-05-04 20:56:09 -04:00
David Kuder 6e7d80e916 Flags for interplation rendering 2023-05-04 20:55:25 -04:00
David Kuder 3ee0061fdc Timing tweaks 2023-05-04 20:54:15 -04:00
David Kuder 4586bb8638 Analog GS Jumper sets machine type fix 2023-05-04 20:54:04 -04:00
16 changed files with 4362 additions and 197 deletions

View File

@ -21,27 +21,27 @@
; x - select Data, active low
.wrap_target
next_bus_cycle:
set PINS, 0b011 ; enable AddrHi tranceiver
wait 1 GPIO, PHI0_GPIO ; wait for PHI0 to rise. Data propagation through the transceiver should
; be complete by the time this happens.
set PINS, 0b011 ; disable tranceivers
wait 1 GPIO, PHI0_GPIO [5] ; wait for PHI0 to rise.
set PINS, 0b011 [5] ; enable AddrHi tranceiver and delay for transceiver propagation delay (24ns)
in PINS, 8 ; read AddrHi[7:0]
set PINS, 0b101 [12] ; enable AddrLo tranceiver and delay for transceiver propagation delay
set PINS, 0b101 [5] ; enable AddrLo tranceiver and delay for transceiver propagation delay (24ns)
in PINS, 8 ; read AddrLo[7:0]
jmp PIN, read_cycle ; jump based on the state of the R/W pin
write_cycle:
; the current time is P0+82ns (P0 + 10ns + 2 clocks (input synchronizers) + 16 instructions)
; the current time is P0+92ns (P0 + 10ns + 2 clocks (input synchronizers) + 21 instructions)
set PINS, 0b110 [31] ; enable Data tranceiver & wait until both ~DEVSEL and the written data are valid (P0+210ns)
set PINS, 0b110 [31] ; enable Data tranceiver & wait until both ~DEVSEL and the written data are valid (P0+220ns)
in PINS, 10 ; read R/W, ~DEVSEL, and Data[7:0], then autopush
wait 0 GPIO, PHI0_GPIO [7] ; wait for PHI0 to fall
jmp next_bus_cycle
read_cycle:
; the current time is P0+82ns (P0 + 10ns + 2 clocks (input synchronizers) + 16 instructions)
; the current time is P0+92ns (P0 + 10ns + 2 clocks (input synchronizers) + 21 instructions)
set PINS, 0b110 [4] ; ensure AddrLo transceiver is disabled and delay for ~DEVSEL to become valid (P0+102ns+buffer delay)
set PINS, 0b110 [5] ; ensure AddrLo transceiver is disabled and delay for ~DEVSEL to become valid (P0+102ns+buffer delay)
in PINS, 10 ; read R/W, ~DEVSEL, and dontcare[7:0], then autopush
irq set READ_DATA_TRIGGER_IRQ ; trigger the data read state machine to put data on the data bus
@ -66,26 +66,26 @@ wait_loop:
wait 1 irq READ_DATA_TRIGGER_IRQ ; wait for the data portion of a read cycle (from the main SM)
jmp PIN, wait_loop ; skip if this device is not being addressed
; the current time is P0+114ns (P0 + 10ns + 2 clocks (input synchronizers) + 24 instructions) and
; the current time is P0+128ns and
; this read cycle is addressed to this device.
;
; Phase 0 is typically 489 ns long.
; * Data from peripherals should be valid on the data bus by 45 nanoseconds before the end of phase 0
; * Data should be held for 40ns after phase 0 ends
; * Data bus should be tri-stated within 60ns after phase 0 ends
; * Data should be held for no more than 20ns after phase 0 ends
; * Data bus should be tri-stated within 30ns after phase 0 ends
irq set DATA_BUSY_IRQ
set PINS, 0b01 [10] ; enable Data tranceiver with output direction [160ns]
mov OSR, ~NULL [31] ; [288ns]
out PINDIRS, 8 [31] ; set data pins as outputs [416ns]
set PINS, 0b01 [7] ; enable Data tranceiver with output direction [P0+164ns]
mov OSR, ~NULL [31] ; [P0+292ns]
out PINDIRS, 8 [31] ; set data pins as outputs [P0+420ns]
pull noblock ; pull value from the FIFO as late as possible [420ns]
out PINS, 8 ; [424ns]
pull noblock ; pull value from the FIFO as late as possible [P0+424ns]
out PINS, 8 ; [P0+428ns]
; the current time is P0+424ns (P0 + 10ns + 2 clocks (input synchronizers) + 101 instructions)
; the current time is P0+428ns
wait 0 GPIO, PHI0_GPIO [7] ; wait for PHI0 to fall then hold for 40ns (2 clocks (input synchronizers) + 7 instructions)
wait 0 GPIO, PHI0_GPIO [2] ; wait for PHI0 to fall then hold for 12ns (2 clocks (input synchronizers) + 7 instructions)
set PINS, 0b10 ; disable Data tranceiver to tri-state the data bus
mov OSR, NULL

View File

@ -12,7 +12,7 @@
; * IN pins are mapped to ~DEVSEL, R/W, and Data[7:0]
; * SET pins are mapped to the transceiver enable signals
; * input shift left & autopush @ 26 bits
; * run at about 125MHz (8ns/instruction)
; * run at about 250MHz (4ns/instruction)
;
; SET bits for tranceiver control:
; 0bxxx
@ -21,31 +21,31 @@
; x - select Data, active low
.wrap_target
next_bus_cycle:
set PINS, 0b011 ; enable AddrHi tranceiver
wait 1 GPIO, PHI0_GPIO ; wait for PHI0 to rise. Data propagation through the transceiver should
; be complete by the time this happens.
set PINS, 0b011 ; disable tranceivers
wait 1 GPIO, PHI0_GPIO [2] ; wait for PHI0 to rise.
set PINS, 0b011 [2] ; enable AddrHi tranceiver and delay for transceiver propagation delay (24ns)
in PINS, 8 ; read AddrHi[7:0]
set PINS, 0b101 [2] ; enable AddrLo tranceiver and delay for transceiver propagation delay
set PINS, 0b101 [2] ; enable AddrLo tranceiver and delay for transceiver propagation delay (24ns)
in PINS, 8 ; read AddrLo[7:0]
jmp PIN, read_cycle ; jump based on the state of the R/W pin
write_cycle:
; the current time is P0+88ns (P0 + 16ns + 2 clocks (input synchronizers) + 7 instructions)
; the current time is P0+98ns (P0 + 10ns + 2 clocks (input synchronizers) + 11 instructions)
set PINS, 0b110 [15] ; enable Data tranceiver & wait until both ~DEVSEL and the written data are valid (P0+200ns)
set PINS, 0b110 [31] ; enable Data tranceiver & wait until both ~DEVSEL and the written data are valid (P0+216ns)
in PINS, 10 ; read R/W, ~DEVSEL, and Data[7:0], then autopush
wait 0 GPIO, PHI0_GPIO [7] ; wait for PHI0 to fall
wait 0 GPIO, PHI0_GPIO [3] ; wait for PHI0 to fall
jmp next_bus_cycle
read_cycle:
; the current time is P0+88ns (P0 + 16ns + 2 clocks (input synchronizers) + 7 instructions)
; the current time is P0+98ns (P0 + 10ns + 2 clocks (input synchronizers) + 11 instructions)
set PINS, 0b110 ; ensure AddrLo transceiver is disabled and delay for ~DEVSEL to become valid (P0+63ns+buffer delay)
set PINS, 0b110 [2] ; ensure AddrLo transceiver is disabled and delay for ~DEVSEL to become valid (P0+102ns+buffer delay)
in PINS, 10 ; read R/W, ~DEVSEL, and dontcare[7:0], then autopush
irq set READ_DATA_TRIGGER_IRQ ; trigger the data read state machine to put data on the data bus
wait 0 GPIO, PHI0_GPIO [7] ; wait for PHI0 to fall
wait 0 GPIO, PHI0_GPIO [3] ; wait for PHI0 to fall
wait 0 irq DATA_BUSY_IRQ ; wait for the data handling state machine to complete to avoid contention w/transceiver control
.wrap
@ -66,32 +66,32 @@ wait_loop:
wait 1 irq READ_DATA_TRIGGER_IRQ ; wait for the data portion of a read cycle (from the main SM)
jmp PIN, wait_loop ; skip if this device is not being addressed
; the current time is P0+136ns (P0 + 16ns + 2 clocks (input synchronizers) + 13 instructions) and
; the current time is P0+138ns and
; this read cycle is addressed to this device.
;
; Phase 0 is typically 489 ns long.
; * Data from peripherals should be valid on the data bus by 45 nanoseconds before the end of phase 0
; * Data should be held for 40ns after phase 0 ends
; * Data bus should be tri-stated within 60ns after phase 0 ends
; * Data should be held for no more than 20ns after phase 0 ends
; * Data bus should be tri-stated within 30ns after phase 0 ends
irq set DATA_BUSY_IRQ
set PINS, 0b01 ; enable Data tranceiver with output direction
mov OSR, ~NULL [4]
out PINDIRS, 8 [31] ; set data pins as outputs
set PINS, 0b01 [3] ; enable Data tranceiver with output direction [P0+178ns]
mov OSR, ~NULL [15] ; [P0+306ns]
out PINDIRS, 8 [15] ; set data pins as outputs [P0+434ns]
pull noblock ; pull value from the FIFO as late as possible
out PINS, 8
pull noblock ; pull value from the FIFO as late as possible [P0+442ns]
out PINS, 8 ; [P0+450ns]
; the current time is P0+440ns (P0 + 16ns + 2 clocks (input synchronizers) + 51 instructions)
; the current time is P0+450ns
wait 0 GPIO, PHI0_GPIO [2] ; wait for PHI0 to fall then hold for 40ns (2 clocks (input synchronizers) + 2-3 instructions)
wait 0 GPIO, PHI0_GPIO [1] ; wait for PHI0 to fall then hold for 16ns (2 clocks (input synchronizers) + 7 instructions)
set PINS, 0b10 ; disable Data tranceiver to tri-state the data bus
mov OSR, NULL
out PINDIRS, 8 ; reset data pins as inputs
pull noblock ; extra late pull to clear out any standing values from the FIFO
pull noblock ; extra late pull to clear out any standing values from the FIFO [P1+56ns]
irq clear DATA_BUSY_IRQ
.wrap

View File

@ -1,7 +1,7 @@
#include "buffers.h"
volatile uint32_t soft_switches = 0;
volatile uint32_t internal_flags = IFLAGS_V7_MODE3;
volatile uint32_t internal_flags = IFLAGS_OLDCOLOR | IFLAGS_INTERP | IFLAGS_V7_MODE3;
volatile uint8_t reset_state = 0;

View File

@ -31,6 +31,9 @@ extern volatile uint8_t *hgr_p4;
/* Videx VideoTerm */
extern volatile uint8_t *videx_page;
#define apple_tbcolor apple_memory[0xC022]
#define apple_border apple_memory[0xC034]
#endif
extern volatile uint8_t *baseio;
@ -107,6 +110,8 @@ extern volatile uint32_t internal_flags;
#define SOFTSW_SHADOW_IO 0x04000000ul
// V2 Analog specific softswitches
#define IFLAGS_INTERP 0x01000000ul
#define IFLAGS_GRILL 0x02000000ul
#define IFLAGS_VIDEO7 0x04000000ul
#define IFLAGS_OLDCOLOR 0x08000000ul
#define IFLAGS_TERMINAL 0x10000000ul

View File

@ -1,6 +1,6 @@
#define BUILDDATE 0x20230502
#define BUILDID 0x0182
#define BUILDSTR " 2 May 2023 Build 0182"
#define BUILDDATE 0x20230504
#define BUILDID 0x0187
#define BUILDSTR " 4 May 2023 Build 0187"
#ifdef ANALOG_GS
#define HWSTRING " V2 Analog GS Rev1"

View File

@ -58,3 +58,6 @@
#define CFGTOKEN_VIDEO7 0x00003756 // "V7\xXX\x00" Video 7 Enable / Disable
#define CFGTOKEN_RGBCOLOR 0x00005043 // "CP\xXX\x04" RGB Palette Entry Override
#define CFGTOKEN_INTERP 0x00004956 // "VI\x0X\x00" RGB Interpolation
#define CFGTOKEN_GRILL 0x00004756 // "VG\x0X\x00" RGB Aperture Grill

View File

@ -201,7 +201,15 @@ void DELAYED_COPY_CODE(default_config)() {
current_machine = MACHINE_AUTO;
internal_flags |= (IFLAGS_IIE_REGS | IFLAGS_IIGS_REGS);
#endif
#ifdef FUNCTION_VGA
apple_tbcolor = 0xf0;
apple_border = 0x00;
terminal_tbcolor = 0xf0;
terminal_border = 0x00;
internal_flags |= IFLAGS_VIDEO7 | IFLAGS_V7_MODE3;
#endif
}
int DELAYED_COPY_CODE(make_config)(uint32_t rev) {
@ -753,10 +761,18 @@ void DELAYED_COPY_CODE(config_handler)() {
break;
case 'R':
// Reboot and bypass auto-detection of machine type.
cfg_machine = current_machine;
write_config(true);
flash_reboot();
switch(config_cmdbuf[1]) {
default:
retval = REPLY_ECMD;
break;
case 'b':
// Reboot and bypass auto-detection of machine type.
cfg_machine = current_machine;
read_config();
write_config(true);
flash_reboot();
break;
}
break;
case 'I':

View File

@ -79,12 +79,15 @@ static void __noinline __time_critical_func(core1_loop)() {
}
#ifdef FUNCTION_VGA
} else if(current_machine == MACHINE_AUTO) {
#ifdef ANALOG_GS
if(value & 0x08000000) {
// Hardware jumpered for IIGS mode.
current_machine = MACHINE_IIGS;
internal_flags &= ~IFLAGS_IIE_REGS;
internal_flags |= IFLAGS_IIGS_REGS;
} else if((apple_memory[0x404] == 0xE5) && (apple_memory[0x0403] == 0xD8)) { // ROMXe
} else
#endif
if((apple_memory[0x404] == 0xE5) && (apple_memory[0x0403] == 0xD8)) { // ROMXe
current_machine = MACHINE_IIE;
internal_flags |= IFLAGS_IIE_REGS;
internal_flags &= ~IFLAGS_IIGS_REGS;
@ -136,7 +139,8 @@ static void __noinline __time_critical_func(core1_loop)() {
soft_switches |= SOFTSW_TEXT_MODE;
soft_switches &= ~SOFTSW_80COL;
soft_switches &= ~SOFTSW_DGR;
internal_flags &= ~(IFLAGS_TERMINAL | IFLAGS_TEST | IFLAGS_V7_MODE3);
internal_flags &= ~(IFLAGS_TERMINAL | IFLAGS_TEST);
internal_flags |= IFLAGS_V7_MODE3;
#endif
default:
reset_state = 0;

View File

@ -55,9 +55,12 @@ void __time_critical_func(vga_businterface)(uint32_t address, uint32_t value) {
return;
}
}
// Nothing left to do for RAM accesses.
if(address < 0xc000) return;
// Shadow the soft-switches by observing all read & write bus cycles
if((address & 0xff80) == 0xc000) {
if(address < 0xc080) {
switch(address & 0x7f) {
case 0x00:
if((internal_flags & (IFLAGS_IIGS_REGS | IFLAGS_IIE_REGS)) && ACCESS_WRITE) {
@ -210,7 +213,7 @@ void __time_critical_func(vga_businterface)(uint32_t address, uint32_t value) {
break;
}
} else if(romx_unlocked == 3) {
if((address & 0xFFF0) == 0xF810) {
if((address >> 4) == 0xF81) {
romx_textbank = address & 0xF;
}
if(address == 0xF851) {
@ -237,10 +240,10 @@ void __time_critical_func(vga_businterface)(uint32_t address, uint32_t value) {
break;
}
} else if(romx_unlocked == 3) {
if((address & 0xFFF0) == 0xCFD0) {
if((address >> 4) == 0xCFD) {
romx_textbank = address & 0xF;
}
if((address & 0xFFF0) == 0xCFE0) {
if((address >> 4) == 0xCFE) {
romx_changed = 1;
romx_unlocked = 0;
}
@ -268,6 +271,16 @@ void __time_critical_func(vga_businterface)(uint32_t address, uint32_t value) {
} else {
internal_flags &= ~IFLAGS_VIDEO7;
}
if(value & 2) {
internal_flags |= IFLAGS_GRILL;
} else {
internal_flags &= ~IFLAGS_GRILL;
}
if(value & 1) {
internal_flags |= IFLAGS_INTERP;
} else {
internal_flags &= ~IFLAGS_INTERP;
}
apple_memory[address] = value;
break;
case 0x02:
@ -289,10 +302,12 @@ void __time_critical_func(vga_businterface)(uint32_t address, uint32_t value) {
apple_memory[address] = (terminal_fifo_rdptr - terminal_fifo_wrptr);
break;
case 0x0B:
#if 0
if((value & 0xFF) <= 0x27) {
romx_textbank = (value & 0xFF);
romx_changed = 1;
}
#endif
break;
case 0x0C:
apple_memory[address] = value;

4098
vga/dhgr_patterns.h Normal file

File diff suppressed because it is too large Load Diff

View File

@ -100,19 +100,21 @@ void DELAYED_COPY_CODE(update_status_left)(const char *str) {
}
void DELAYED_COPY_CODE(render_init)() {
int i;
switch_font();
// Initialize "Half-Palette" for aperture grill effect
for(int i = 1; i < 15; i++) {
half_palette[i] = (dhgr_palette[i] >> 1) & _RGBHALF;
lhalf_palette[i] = (lores_palette[i] >> 1) & _RGBHALF;
}
half_palette[0] = dhgr_palette[0];
half_palette[15] = dhgr_palette[15];
lhalf_palette[0] = lores_palette[0];
lhalf_palette[15] = lores_palette[15];
if((soft_switches & SOFTSW_MODE_MASK) == 0)
internal_flags |= IFLAGS_TEST;
apple_tbcolor = 0xf0;
apple_border = 0x00;
terminal_tbcolor = 0xf0;
terminal_border = 0x00;
memcpy(terminal_character_rom, (void*)FLASH_VIDEX_BASE, 4096);
memset(status_line, 0, sizeof(status_line));

View File

@ -5,6 +5,8 @@
// Uncomment to enable test patter generator
#define RENDER_TEST_PATTERN
extern uint16_t lhalf_palette[16];
extern uint16_t half_palette[16];
extern uint16_t lores_palette[16];
extern uint16_t dhgr_palette[16];

View File

@ -7,8 +7,6 @@
//#define PAGE2SEL (!(soft_switches & SOFTSW_80STORE) && (soft_switches & SOFTSW_PAGE_2))
#define PAGE2SEL ((soft_switches & (SOFTSW_80STORE | SOFTSW_PAGE_2)) == SOFTSW_PAGE_2)
extern uint16_t dhgr_palette[16];
uint8_t DELAYED_COPY_DATA(dgr_dot_pattern)[32] = {
0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
0x08, 0x19, 0x2A, 0x3B, 0x4C, 0x5D, 0x6E, 0x7F,
@ -16,6 +14,11 @@ uint8_t DELAYED_COPY_DATA(dgr_dot_pattern)[32] = {
0x22, 0x66, 0x2A, 0x6E, 0x33, 0x77, 0x3B, 0x7F,
};
extern uint8_t lores_to_dhgr[16];
uint8_t dhgr_to_lores[16] = {
0,2,4,6,8,10,12,14,1,3,5,7,9,11,13,15
};
static void render_dgr_line(bool p2, uint line);
void DELAYED_COPY_CODE(render_dgr)() {
@ -59,9 +62,11 @@ static void DELAYED_COPY_CODE(render_dgr_line)(bool p2, uint line) {
sl_pos++;
i = 0;
color1 = 0;
color2 = 0;
if(mono_rendering) {
while(i < 40) {
while((dotc <= 18) && (i < 40)) {
while((dotc <= 14) && (i < 40)) {
color1 |= dgr_dot_pattern[((i & 1) << 4) | (line_bufb[i] & 0xf)] << dotc;
color2 |= dgr_dot_pattern[((i & 1) << 4) | ((line_bufb[i] >> 4) & 0xf)] << dotc;
dotc += 7;
@ -88,28 +93,8 @@ static void DELAYED_COPY_CODE(render_dgr_line)(bool p2, uint line) {
}
}
} else {
// Preload the first 14 subpixels
color1 = dgr_dot_pattern[line_bufb[i] & 0xf] << dotc;
color2 = dgr_dot_pattern[(line_bufb[i] >> 4) & 0xf] << dotc;
dotc += 7;
color1 |= dgr_dot_pattern[(line_bufa[i] & 0xf)] << dotc;
color2 |= dgr_dot_pattern[((line_bufa[i] >> 4) & 0xf)] << dotc;
dotc += 7;
i++;
// First two pixels
pixeldata = dhgr_palette[0];
pixeldata |= ((dhgr_palette[color1 & 0xf] >> 1) & _RGBHALF) << 16;
sl1->data[sl_pos] = pixeldata;
pixeldata = dhgr_palette[0];
pixeldata |= ((dhgr_palette[color1 & 0xf] >> 1) & _RGBHALF) << 16;
sl2->data[sl_pos] = pixeldata;
sl_pos++;
while(i < 40) {
// Load in as many subpixels as possible
while((dotc <= 18) && (i < 40)) {
while((dotc <= 14) && (i < 40)) {
color1 |= dgr_dot_pattern[((i & 1) << 4) | (line_bufb[i] & 0xf)] << dotc;
color2 |= dgr_dot_pattern[((i & 1) << 4) | ((line_bufb[i] >> 4) & 0xf)] << dotc;
dotc += 7;
@ -120,43 +105,43 @@ static void DELAYED_COPY_CODE(render_dgr_line)(bool p2, uint line) {
}
// Consume pixels
while(dotc >= 8) {
pixeldata = (dhgr_palette[color1 & 0xf]);
pixeldata |= ((dhgr_palette[color1 & 0xf] >> 1) & _RGBHALF) << 16;
while((dotc >= 8) || ((dotc > 0) && (i == 40))) {
color1 &= 0xfffffffe;
color1 |= (color1 >> 4) & 1;
pixeldata = dhgr_palette[color1 & 0xf];
color1 &= 0xfffffffc;
color1 |= (color1 >> 4) & 3;
pixeldata |= dhgr_palette[color1 & 0xf] << 16;
sl1->data[sl_pos] = pixeldata;
pixeldata = (dhgr_palette[color2 & 0xf]);
pixeldata |= ((dhgr_palette[color2 & 0xf] >> 1) & _RGBHALF) << 16;
color2 &= 0xfffffffe;
color2 |= (color2 >> 4) & 1;
pixeldata = dhgr_palette[color2 & 0xf];
color2 &= 0xfffffffc;
color2 |= (color2 >> 4) & 3;
pixeldata |= dhgr_palette[color2 & 0xf] << 16;
sl2->data[sl_pos] = pixeldata;
sl_pos++;
pixeldata = (dhgr_palette[(color1 & 0xc) | ((color1 & 0x30) >> 4)]);
pixeldata |= ((dhgr_palette[(color1 & 0xf0) >> 4] >> 1) & _RGBHALF) << 16;
sl1->data[sl_pos] = pixeldata;
pixeldata = (dhgr_palette[(color2 & 0xc) | ((color2 & 0x30) >> 4)]);
pixeldata |= ((dhgr_palette[(color2 & 0xf0) >> 4] >> 1) & _RGBHALF) << 16;
sl2->data[sl_pos] = pixeldata;
sl_pos++;
color1 &= 0xfffffff8;
color1 |= (color1 >> 4) & 7;
pixeldata = dhgr_palette[color1 & 0xf];
color1 >>= 4;
pixeldata |= dhgr_palette[color1 & 0xf] << 16;
sl1->data[sl_pos] = pixeldata;
color2 &= 0xfffffff8;
color2 |= (color2 >> 4) & 7;
pixeldata = dhgr_palette[color2 & 0xf];
color2 >>= 4;
pixeldata |= dhgr_palette[color2 & 0xf] << 16;
sl2->data[sl_pos] = pixeldata;
sl_pos++;
dotc -= 4;
}
}
// Last two pixels
pixeldata = (dhgr_palette[color1 & 0xf]);
pixeldata |= ((dhgr_palette[color1 & 0xf] >> 1) & _RGBHALF) << 16;
sl1->data[sl_pos] = pixeldata;
pixeldata = (dhgr_palette[color2 & 0xf]);
pixeldata |= ((dhgr_palette[color2 & 0xf] >> 1) & _RGBHALF) << 16;
sl2->data[sl_pos] = pixeldata;
sl_pos++;
}
// Pad 40 pixels on the right to center horizontally

View File

@ -5,6 +5,7 @@
#include "vga/vgabuf.h"
#include "vga/render.h"
#include "vga/vgaout.h"
#include "vga/dhgr_patterns.h"
static void render_dhgr_line(bool p2, uint line, bool mono);
@ -14,6 +15,7 @@ uint16_t DELAYED_COPY_DATA(dhgr_palette)[16] = {
RGB_MAGENTA, RGB_HVIOLET, RGB_DGRAY, RGB_LBLUE,
RGB_HORANGE, RGB_PINK, RGB_YELLOW, RGB_WHITE
};
uint16_t __attribute__((section(".uninitialized_data."))) half_palette[16];
//#define PAGE2SEL (!(soft_switches & SOFTSW_80STORE) && (soft_switches & SOFTSW_PAGE_2))
#define PAGE2SEL ((soft_switches & (SOFTSW_80STORE | SOFTSW_PAGE_2)) == SOFTSW_PAGE_2)
@ -67,6 +69,9 @@ static void DELAYED_COPY_CODE(render_dhgr_line)(bool p2, uint line, bool mono) {
uint32_t dots = 0;
uint_fast8_t dotc = 0;
uint32_t pixeldata;
uint32_t pixelmode = 0;
uint16_t white_pixel_count = 0;
uint32_t color1, color2, color3, color4;
i = 0;
if(mono) {
@ -91,7 +96,6 @@ static void DELAYED_COPY_CODE(render_dhgr_line)(bool p2, uint line, bool mono) {
}
}
} else if((internal_flags & IFLAGS_VIDEO7) && ((soft_switches & (SOFTSW_80STORE | SOFTSW_80COL)) == (SOFTSW_80STORE))) {
uint32_t color1, color2, color3, color4;
int j;
// Video 7 F/B HiRes
@ -150,7 +154,118 @@ static void DELAYED_COPY_CODE(render_dhgr_line)(bool p2, uint line, bool mono) {
dotc -= 8;
}
}
} else if(internal_flags & IFLAGS_OLDCOLOR) {
} else if((internal_flags & (IFLAGS_VIDEO7 | IFLAGS_V7_MODE3)) == (IFLAGS_VIDEO7 | IFLAGS_V7_MODE1)) {
// Video-7 Mixed B&W/RGB
while(i < 40) {
// Load in as many subpixels as possible
while((dotc <= 18) && (i < 40)) {
dots |= (line_memb[i] & 0x7f) << dotc;
pixelmode |= ((line_memb[i] & 0x80) ? 0x7f : 0x00) << dotc;
dotc += 7;
dots |= (line_mema[i] & 0x7f) << dotc;
pixelmode |= ((line_mema[i] & 0x80) ? 0x7f : 0x00) << dotc;
dotc += 7;
i++;
}
// Consume pixels
while(dotc >= 4) {
if(pixelmode) {
pixeldata = (dhgr_palette[dots & 0xf] | THEN_EXTEND_1);
pixeldata |= pixeldata << 16;
dots >>= 4;
pixelmode >>= 4;
sl->data[sl_pos++] = pixeldata;
dotc -= 4;
} else {
pixeldata = ((dots & 1) ? (text_fore) : (text_back));
dots >>= 1;
pixelmode >>= 1;
pixeldata |= (((dots & 1) ? (text_fore) : (text_back))) << 16;
dots >>= 1;
pixelmode >>= 1;
sl->data[sl_pos++] = pixeldata;
dotc -= 2;
pixeldata = ((dots & 1) ? (text_fore) : (text_back));
dots >>= 1;
pixelmode >>= 1;
pixeldata |= (((dots & 1) ? (text_fore) : (text_back))) << 16;
dots >>= 1;
pixelmode >>= 1;
sl->data[sl_pos++] = pixeldata;
dotc -= 2;
}
}
}
} else if((internal_flags & (IFLAGS_INTERP | IFLAGS_GRILL)) == (IFLAGS_INTERP | IFLAGS_GRILL)) {
// Preload black into the sliding window
dots = 0;
dotc = 4;
while(i < 40) {
// Load in as many subpixels as possible
while((dotc <= 18) && (i < 40)) {
dots |= (line_memb[i] & 0x7f) << dotc;
dotc += 7;
dots |= (line_mema[i] & 0x7f) << dotc;
dotc += 7;
i++;
}
while((dotc >= 8) || ((dotc > 0) && (i == 40))) {
dots &= 0xfffffffe;
dots |= (dots >> 4) & 1;
pixeldata = half_palette[dots & 0xf];
dots &= 0xfffffffc;
dots |= (dots >> 4) & 3;
pixeldata |= dhgr_palette[dots & 0xf] << 16;
sl->data[sl_pos++] = pixeldata;
dots &= 0xfffffff8;
dots |= (dots >> 4) & 7;
pixeldata = half_palette[dots & 0xf];
dots >>= 4;
pixeldata |= dhgr_palette[dots & 0xf] << 16;
sl->data[sl_pos++] = pixeldata;
dotc -= 4;
}
}
} else if(internal_flags & IFLAGS_INTERP) {
// Preload black into the sliding window
dots = 0;
dotc = 4;
while(i < 40) {
// Load in as many subpixels as possible
while((dotc <= 18) && (i < 40)) {
dots |= (line_memb[i] & 0x7f) << dotc;
dotc += 7;
dots |= (line_mema[i] & 0x7f) << dotc;
dotc += 7;
i++;
}
while((dotc >= 8) || ((dotc > 0) && (i == 40))) {
dots &= 0xfffffffe;
dots |= (dots >> 4) & 1;
pixeldata = dhgr_palette[dots & 0xf];
dots &= 0xfffffffc;
dots |= (dots >> 4) & 3;
pixeldata |= dhgr_palette[dots & 0xf] << 16;
sl->data[sl_pos++] = pixeldata;
dots &= 0xfffffff8;
dots |= (dots >> 4) & 7;
pixeldata = dhgr_palette[dots & 0xf];
dots >>= 4;
pixeldata |= dhgr_palette[dots & 0xf] << 16;
sl->data[sl_pos++] = pixeldata;
dotc -= 4;
}
}
} else {
while(i < 40) {
// Load in as many subpixels as possible
while((dotc <= 18) && (i < 40)) {
@ -171,46 +286,6 @@ static void DELAYED_COPY_CODE(render_dhgr_line)(bool p2, uint line, bool mono) {
dotc -= 8;
}
}
} else {
// Preload the first 14 subpixels
dots |= (line_memb[i] & 0x7f) << dotc;
dotc += 7;
dots |= (line_mema[i] & 0x7f) << dotc;
dotc += 7;
i++;
// First two pixels
pixeldata = dhgr_palette[0];
pixeldata |= ((dhgr_palette[dots & 0xf] >> 1) & _RGBHALF) << 16;
sl->data[sl_pos++] = pixeldata;
while(i < 40) {
// Load in as many subpixels as possible
while((dotc <= 18) && (i < 40)) {
dots |= (line_memb[i] & 0x7f) << dotc;
dotc += 7;
dots |= (line_mema[i] & 0x7f) << dotc;
dotc += 7;
i++;
}
// Consume pixels
while(dotc >= 8) {
pixeldata = (dhgr_palette[dots & 0xf]);
pixeldata |= ((dhgr_palette[dots & 0xf] >> 1) & _RGBHALF) << 16;
sl->data[sl_pos++] = pixeldata;
pixeldata = (dhgr_palette[(dots & 0xc) | ((dots & 0x30) >> 4)]);
pixeldata |= ((dhgr_palette[(dots & 0xf0) >> 4] >> 1) & _RGBHALF) << 16;
sl->data[sl_pos++] = pixeldata;
dots >>= 4;
dotc -= 4;
}
}
// Last two pixels
pixeldata = (dhgr_palette[dots & 0xf]);
pixeldata |= ((dhgr_palette[dots & 0xf] >> 1) & _RGBHALF) << 16;
sl->data[sl_pos++] = pixeldata;
}
if((internal_flags & IFLAGS_VIDEO7) && ((internal_flags & IFLAGS_V7_MODE3) == IFLAGS_V7_MODE2)) {

View File

@ -8,6 +8,7 @@
//#define PAGE2SEL (!(soft_switches & SOFTSW_80STORE) && (soft_switches & SOFTSW_PAGE_2))
#define PAGE2SEL ((soft_switches & (SOFTSW_80STORE | SOFTSW_PAGE_2)) == SOFTSW_PAGE_2)
uint16_t __attribute__((section(".uninitialized_data."))) lhalf_palette[16];
static void render_hires_line(bool p2, uint line);
@ -66,7 +67,7 @@ static void DELAYED_COPY_CODE(render_hires_line)(bool p2, uint line) {
dotc -= 2;
}
}
} else if(internal_flags & IFLAGS_OLDCOLOR) {
} else {
// Each hires byte contains 7 pixels which may be shifted right 1/2 a pixel. That is
// represented here by 14 'dots' to precisely describe the half-pixel positioning.
//
@ -109,44 +110,6 @@ static void DELAYED_COPY_CODE(render_hires_line)(bool p2, uint line) {
oddness ^= 0x100;
}
}
} else {
// Preload the first 14 subpixels
dots = (hires_dot_patterns2[line_mem[i]]);
lastmsb = (dotc>0) ? ((line_mem[i] & 0x40)<<2) : 0;
i++;
dotc = 14;
// First two pixels
pixeldata = lores_palette[0];
pixeldata |= ((lores_palette[dots & 0xf] >> 1) & _RGBHALF) << 16;
sl->data[sl_pos++] = pixeldata;
while(i < 40) {
// Load in as many subpixels as possible
if((dotc < 18) && (i < 40)) {
dots |= (hires_dot_patterns2[lastmsb | line_mem[i]]) << dotc;
lastmsb = (dotc>0) ? ((line_mem[i] & 0x40)<<2) : 0;
i++;
dotc += 14;
}
// Consume pixels
while(dotc >= 8) {
pixeldata = (lores_palette[dots & 0xf]);
pixeldata |= ((lores_palette[dots & 0xf] >> 1) & _RGBHALF) << 16;
sl->data[sl_pos++] = pixeldata;
pixeldata = (lores_palette[(dots & 0xc) | ((dots & 0x30) >> 4)]);
pixeldata |= ((lores_palette[(dots & 0xf0) >> 4] >> 1) & _RGBHALF) << 16;
sl->data[sl_pos++] = pixeldata;
dots >>= 4;
dotc -= 4;
}
}
// Last two pixels
pixeldata = (lores_palette[dots & 0xf]);
pixeldata |= ((lores_palette[dots & 0xf] >> 1) & _RGBHALF) << 16;
sl->data[sl_pos++] = pixeldata;
}
// Pad 40 pixels on the right to center horizontally

View File

@ -17,9 +17,6 @@ extern uint8_t terminal_fifo_rdptr;
extern volatile uint8_t terminal_row;
extern volatile uint8_t terminal_col;
#define apple_tbcolor apple_memory[0xC022]
#define apple_border apple_memory[0xC034]
#define APPLE_FORE ((apple_tbcolor>>4) & 0xf)
#define APPLE_BACK (apple_tbcolor & 0xf)
#define APPLE_BORDER (apple_border & 0xf)