mirror of
https://github.com/V2RetroComputing/analog-firmware.git
synced 2025-04-18 03:37:00 +00:00
Initial import
This commit is contained in:
parent
e7c9581cbe
commit
53aa7efca2
146
CMakeLists.txt
Normal file
146
CMakeLists.txt
Normal file
@ -0,0 +1,146 @@
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
|
||||
if(${CMAKE_CURRENT_BINARY_DIR} MATCHES "-gs")
|
||||
set(PICO_BOARD pico)
|
||||
set(BINARY_TAGS "${BINARY_TAGS}-gs")
|
||||
message(STATUS "Building for V2 AnalogGS")
|
||||
elseif(${CMAKE_CURRENT_BINARY_DIR} MATCHES "-lc")
|
||||
set(PICO_BOARD pico)
|
||||
set(BINARY_TAGS "${BINARY_TAGS}-lc")
|
||||
message(STATUS "Building for V2 Analog LC")
|
||||
elseif(${CMAKE_CURRENT_BINARY_DIR} MATCHES "-wifi")
|
||||
set(PICO_BOARD pico_w)
|
||||
set(BINARY_TAGS "${BINARY_TAGS}-wifi")
|
||||
message(STATUS "Building for V2 Analog with WiFi")
|
||||
else()
|
||||
message(FATAL_ERROR "You must specify -lc or -wifi board type.")
|
||||
endif()
|
||||
|
||||
if(${CMAKE_CURRENT_BINARY_DIR} MATCHES "-4ns")
|
||||
set(BINARY_TAGS "${BINARY_TAGS}-4ns")
|
||||
message(STATUS "SYSCLOCK will be 252MHz")
|
||||
elseif(${CMAKE_CURRENT_BINARY_DIR} MATCHES "-8ns")
|
||||
set(BINARY_TAGS "${BINARY_TAGS}-8ns")
|
||||
message(STATUS "SYSCLOCK will be 126MHz")
|
||||
else()
|
||||
message(FATAL_ERROR "You must specify -4ns (252MHz) or -8ns (126MHz) speed.")
|
||||
endif()
|
||||
|
||||
if(${CMAKE_CURRENT_BINARY_DIR} MATCHES "-vga")
|
||||
set(BINARY_TAGS "${BINARY_TAGS}-vga")
|
||||
message(STATUS "VGA Function Enabled")
|
||||
elseif(${CMAKE_CURRENT_BINARY_DIR} MATCHES "-z80")
|
||||
set(BINARY_TAGS "${BINARY_TAGS}-z80")
|
||||
message(STATUS "Z80 Function Enabled")
|
||||
else()
|
||||
message(FATAL_ERROR "You must specify -vga or -z80 function.")
|
||||
endif()
|
||||
|
||||
# Pull in SDK (must be before project)
|
||||
include(cmake/pico_sdk_import.cmake)
|
||||
|
||||
project(v2-analog)
|
||||
set(CMAKE_C_STANDARD 11)
|
||||
|
||||
pico_sdk_init()
|
||||
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DPICO_USE_MALLOC_MUTEX=1")
|
||||
|
||||
add_executable(v2-analog${BINARY_TAGS})
|
||||
|
||||
if(${CMAKE_CURRENT_BINARY_DIR} MATCHES "-gs")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DANALOG_GS=1")
|
||||
endif()
|
||||
|
||||
if(${CMAKE_CURRENT_BINARY_DIR} MATCHES "-4ns")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DCONFIG_SYSCLOCK=252 -DPICO_FLASH_SPI_CLKDIV=8 -DOVERCLOCKED=1")
|
||||
if(${CMAKE_CURRENT_BINARY_DIR} MATCHES "-gs")
|
||||
pico_generate_pio_header(v2-analog${BINARY_TAGS}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/common/abus-gs-4ns.pio)
|
||||
else()
|
||||
pico_generate_pio_header(v2-analog${BINARY_TAGS}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/common/abus-4ns.pio)
|
||||
endif(${CMAKE_CURRENT_BINARY_DIR} MATCHES "-gs")
|
||||
elseif(${CMAKE_CURRENT_BINARY_DIR} MATCHES "-8ns")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DCONFIG_SYSCLOCK=126")
|
||||
if(${CMAKE_CURRENT_BINARY_DIR} MATCHES "-gs")
|
||||
pico_generate_pio_header(v2-analog${BINARY_TAGS}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/common/abus-gs-8ns.pio)
|
||||
else()
|
||||
pico_generate_pio_header(v2-analog${BINARY_TAGS}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/common/abus-8ns.pio)
|
||||
endif(${CMAKE_CURRENT_BINARY_DIR} MATCHES "-gs")
|
||||
endif()
|
||||
|
||||
if(${CMAKE_CURRENT_BINARY_DIR} MATCHES "-vga")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DFUNCTION_VGA=1")
|
||||
if(${CMAKE_CURRENT_BINARY_DIR} MATCHES "-gs")
|
||||
pico_generate_pio_header(v2-analog${BINARY_TAGS}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/vga/vga12.pio)
|
||||
else()
|
||||
pico_generate_pio_header(v2-analog${BINARY_TAGS}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/vga/vga9.pio)
|
||||
endif(${CMAKE_CURRENT_BINARY_DIR} MATCHES "-gs")
|
||||
elseif(${CMAKE_CURRENT_BINARY_DIR} MATCHES "-z80")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DFUNCTION_Z80=1")
|
||||
endif(${CMAKE_CURRENT_BINARY_DIR} MATCHES "-vga")
|
||||
|
||||
target_sources(v2-analog${BINARY_TAGS} PUBLIC
|
||||
common/main.c
|
||||
common/abus.c
|
||||
common/config.c
|
||||
common/dmacopy.c
|
||||
common/buffers.c
|
||||
common/flash.c
|
||||
common/usb_descriptors.c
|
||||
)
|
||||
|
||||
if(${CMAKE_CURRENT_BINARY_DIR} MATCHES "-vga")
|
||||
target_sources(v2-analog${BINARY_TAGS} PUBLIC
|
||||
vga/vgamain.c
|
||||
vga/businterface.c
|
||||
vga/vgabuf.c
|
||||
vga/render.c
|
||||
vga/render_hires.c
|
||||
vga/render_lores.c
|
||||
vga/render_text.c
|
||||
vga/render_80col.c
|
||||
vga/render_dhgr.c
|
||||
vga/render_dgr.c
|
||||
vga/render_shr.c
|
||||
vga/render_test.c
|
||||
vga/vgaout.c
|
||||
)
|
||||
elseif(${CMAKE_CURRENT_BINARY_DIR} MATCHES "-z80")
|
||||
target_sources(v2-analog${BINARY_TAGS} PUBLIC
|
||||
z80/businterface.c
|
||||
z80/z80main.c
|
||||
)
|
||||
endif()
|
||||
|
||||
target_include_directories(v2-analog${BINARY_TAGS} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
target_link_libraries(v2-analog${BINARY_TAGS} PUBLIC
|
||||
pico_multicore
|
||||
pico_stdlib
|
||||
pico_unique_id
|
||||
tinyusb_device
|
||||
tinyusb_board
|
||||
hardware_resets
|
||||
hardware_irq
|
||||
hardware_dma
|
||||
hardware_pio
|
||||
hardware_flash
|
||||
)
|
||||
|
||||
if(${PICO_BOARD} MATCHES "pico_w")
|
||||
target_link_libraries(v2-analog${BINARY_TAGS} PUBLIC
|
||||
pico_cyw43_arch_lwip_poll
|
||||
)
|
||||
endif()
|
||||
|
||||
pico_enable_stdio_usb(v2-analog${BINARY_TAGS} 0)
|
||||
pico_enable_stdio_uart(v2-analog${BINARY_TAGS} 0)
|
||||
|
||||
pico_set_linker_script(v2-analog${BINARY_TAGS} ${PROJECT_SOURCE_DIR}/delayed_copy.ld)
|
||||
|
||||
pico_add_extra_outputs(v2-analog${BINARY_TAGS})
|
20
build.sh
Normal file
20
build.sh
Normal file
@ -0,0 +1,20 @@
|
||||
#!/bin/bash
|
||||
|
||||
if [ -z ${PICO_SDK:+x} ]; then
|
||||
echo You must set PICO_SDK to the path where you downloaded https://github.com/raspberrypi/pico-sdk.git
|
||||
exit 1
|
||||
fi
|
||||
|
||||
build_firmware() {
|
||||
if [ ! -d build/$1 ]; then
|
||||
( mkdir -p build/$1 && cd build/$1 && cmake ../.. )
|
||||
fi
|
||||
make -C build/$1
|
||||
}
|
||||
|
||||
build_firmware v2-analog-lc-4ns-z80
|
||||
build_firmware v2-analog-lc-8ns-z80
|
||||
build_firmware v2-analog-lc-8ns-vga
|
||||
build_firmware v2-analog-wifi-4ns-z80
|
||||
build_firmware v2-analog-wifi-8ns-z80
|
||||
build_firmware v2-analog-wifi-8ns-vga
|
62
cmake/pico_sdk_import.cmake
Normal file
62
cmake/pico_sdk_import.cmake
Normal file
@ -0,0 +1,62 @@
|
||||
# This is a copy of <PICO_SDK_PATH>/external/pico_sdk_import.cmake
|
||||
|
||||
# This can be dropped into an external project to help locate this SDK
|
||||
# It should be include()ed prior to project()
|
||||
|
||||
if (DEFINED ENV{PICO_SDK_PATH} AND (NOT PICO_SDK_PATH))
|
||||
set(PICO_SDK_PATH $ENV{PICO_SDK_PATH})
|
||||
message("Using PICO_SDK_PATH from environment ('${PICO_SDK_PATH}')")
|
||||
endif ()
|
||||
|
||||
if (DEFINED ENV{PICO_SDK_FETCH_FROM_GIT} AND (NOT PICO_SDK_FETCH_FROM_GIT))
|
||||
set(PICO_SDK_FETCH_FROM_GIT $ENV{PICO_SDK_FETCH_FROM_GIT})
|
||||
message("Using PICO_SDK_FETCH_FROM_GIT from environment ('${PICO_SDK_FETCH_FROM_GIT}')")
|
||||
endif ()
|
||||
|
||||
if (DEFINED ENV{PICO_SDK_FETCH_FROM_GIT_PATH} AND (NOT PICO_SDK_FETCH_FROM_GIT_PATH))
|
||||
set(PICO_SDK_FETCH_FROM_GIT_PATH $ENV{PICO_SDK_FETCH_FROM_GIT_PATH})
|
||||
message("Using PICO_SDK_FETCH_FROM_GIT_PATH from environment ('${PICO_SDK_FETCH_FROM_GIT_PATH}')")
|
||||
endif ()
|
||||
|
||||
set(PICO_SDK_PATH "${PICO_SDK_PATH}" CACHE PATH "Path to the Raspberry Pi Pico SDK")
|
||||
set(PICO_SDK_FETCH_FROM_GIT "${PICO_SDK_FETCH_FROM_GIT}" CACHE BOOL "Set to ON to fetch copy of SDK from git if not otherwise locatable")
|
||||
set(PICO_SDK_FETCH_FROM_GIT_PATH "${PICO_SDK_FETCH_FROM_GIT_PATH}" CACHE FILEPATH "location to download SDK")
|
||||
|
||||
if (NOT PICO_SDK_PATH)
|
||||
if (PICO_SDK_FETCH_FROM_GIT)
|
||||
include(FetchContent)
|
||||
set(FETCHCONTENT_BASE_DIR_SAVE ${FETCHCONTENT_BASE_DIR})
|
||||
if (PICO_SDK_FETCH_FROM_GIT_PATH)
|
||||
get_filename_component(FETCHCONTENT_BASE_DIR "${PICO_SDK_FETCH_FROM_GIT_PATH}" REALPATH BASE_DIR "${CMAKE_SOURCE_DIR}")
|
||||
endif ()
|
||||
FetchContent_Declare(
|
||||
pico_sdk
|
||||
GIT_REPOSITORY https://github.com/raspberrypi/pico-sdk
|
||||
GIT_TAG master
|
||||
)
|
||||
if (NOT pico_sdk)
|
||||
message("Downloading Raspberry Pi Pico SDK")
|
||||
FetchContent_Populate(pico_sdk)
|
||||
set(PICO_SDK_PATH ${pico_sdk_SOURCE_DIR})
|
||||
endif ()
|
||||
set(FETCHCONTENT_BASE_DIR ${FETCHCONTENT_BASE_DIR_SAVE})
|
||||
else ()
|
||||
message(FATAL_ERROR
|
||||
"SDK location was not specified. Please set PICO_SDK_PATH or set PICO_SDK_FETCH_FROM_GIT to on to fetch from git."
|
||||
)
|
||||
endif ()
|
||||
endif ()
|
||||
|
||||
get_filename_component(PICO_SDK_PATH "${PICO_SDK_PATH}" REALPATH BASE_DIR "${CMAKE_BINARY_DIR}")
|
||||
if (NOT EXISTS ${PICO_SDK_PATH})
|
||||
message(FATAL_ERROR "Directory '${PICO_SDK_PATH}' not found")
|
||||
endif ()
|
||||
|
||||
set(PICO_SDK_INIT_CMAKE_FILE ${PICO_SDK_PATH}/pico_sdk_init.cmake)
|
||||
if (NOT EXISTS ${PICO_SDK_INIT_CMAKE_FILE})
|
||||
message(FATAL_ERROR "Directory '${PICO_SDK_PATH}' does not appear to contain the Raspberry Pi Pico SDK")
|
||||
endif ()
|
||||
|
||||
set(PICO_SDK_PATH ${PICO_SDK_PATH} CACHE PATH "Path to the Raspberry Pi Pico SDK" FORCE)
|
||||
|
||||
include(${PICO_SDK_INIT_CMAKE_FILE})
|
97
common/abus-4ns.pio
Normal file
97
common/abus-4ns.pio
Normal file
@ -0,0 +1,97 @@
|
||||
.define public PHI0_GPIO 26
|
||||
.define READ_DATA_TRIGGER_IRQ 4
|
||||
.define DATA_BUSY_IRQ 5
|
||||
|
||||
; Apple II bus interface
|
||||
; Ref: Understanding the Apple II, pages 4-7, 7-8
|
||||
|
||||
.program abus
|
||||
; Prerequisites:
|
||||
; * Bus clock used is PHI0, wired to GPIO 26
|
||||
; * JMP pin is mapped to the R/W signal
|
||||
; * 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 250MHz (4ns/instruction)
|
||||
;
|
||||
; SET bits for tranceiver control:
|
||||
; 0bxxx
|
||||
; x - select AddrHi, active low
|
||||
; x - select AddrLo, active low
|
||||
; 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.
|
||||
in PINS, 8 ; read AddrHi[7:0]
|
||||
set PINS, 0b101 [12] ; enable AddrLo tranceiver and delay for transceiver propagation delay
|
||||
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)
|
||||
|
||||
set PINS, 0b110 [31] ; enable Data tranceiver & wait until both ~DEVSEL and the written data are valid (P0+210ns)
|
||||
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)
|
||||
|
||||
set PINS, 0b110 [4] ; 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 irq DATA_BUSY_IRQ ; wait for the data handling state machine to complete to avoid contention w/transceiver control
|
||||
.wrap
|
||||
|
||||
|
||||
.program abus_device_read
|
||||
; Prerequisites:
|
||||
; * Bus clock used is PHI0, wired to GPIO 26
|
||||
; * JMP pin is the ~DEVSEL signal
|
||||
; * OUT pins are the 8 data signals
|
||||
; * SET pins are the Data transceiver control signals
|
||||
;
|
||||
; SET bits for tranceiver control:
|
||||
; 0bxx
|
||||
; x - select Data transceiver (active low)
|
||||
; x - Data transceiver direction (0=input, 1=output)
|
||||
.wrap_target
|
||||
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
|
||||
; 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
|
||||
|
||||
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]
|
||||
|
||||
pull noblock ; pull value from the FIFO as late as possible [420ns]
|
||||
out PINS, 8 ; [424ns]
|
||||
|
||||
; the current time is P0+424ns (P0 + 10ns + 2 clocks (input synchronizers) + 101 instructions)
|
||||
|
||||
wait 0 GPIO, PHI0_GPIO [7] ; wait for PHI0 to fall then hold for 40ns (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 [P1+56ns]
|
||||
|
||||
irq clear DATA_BUSY_IRQ
|
||||
.wrap
|
97
common/abus-8ns.pio
Normal file
97
common/abus-8ns.pio
Normal file
@ -0,0 +1,97 @@
|
||||
.define public PHI0_GPIO 26
|
||||
.define READ_DATA_TRIGGER_IRQ 4
|
||||
.define DATA_BUSY_IRQ 5
|
||||
|
||||
; Apple II bus interface
|
||||
; Ref: Understanding the Apple II, pages 4-7, 7-8
|
||||
|
||||
.program abus
|
||||
; Prerequisites:
|
||||
; * Bus clock used is PHI0, wired to GPIO 26
|
||||
; * JMP pin is mapped to the R/W signal
|
||||
; * 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)
|
||||
;
|
||||
; SET bits for tranceiver control:
|
||||
; 0bxxx
|
||||
; x - select AddrHi, active low
|
||||
; x - select AddrLo, active low
|
||||
; 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.
|
||||
in PINS, 8 ; read AddrHi[7:0]
|
||||
set PINS, 0b101 [2] ; enable AddrLo tranceiver and delay for transceiver propagation delay
|
||||
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)
|
||||
|
||||
set PINS, 0b110 [15] ; enable Data tranceiver & wait until both ~DEVSEL and the written data are valid (P0+200ns)
|
||||
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+88ns (P0 + 16ns + 2 clocks (input synchronizers) + 7 instructions)
|
||||
|
||||
set PINS, 0b110 ; ensure AddrLo transceiver is disabled and delay for ~DEVSEL to become valid (P0+63ns+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 irq DATA_BUSY_IRQ ; wait for the data handling state machine to complete to avoid contention w/transceiver control
|
||||
.wrap
|
||||
|
||||
|
||||
.program abus_device_read
|
||||
; Prerequisites:
|
||||
; * Bus clock used is PHI0, wired to GPIO 26
|
||||
; * JMP pin is the ~DEVSEL signal
|
||||
; * OUT pins are the 8 data signals
|
||||
; * SET pins are the Data transceiver control signals
|
||||
;
|
||||
; SET bits for tranceiver control:
|
||||
; 0bxx
|
||||
; x - select Data transceiver (active low)
|
||||
; x - Data transceiver direction (0=input, 1=output)
|
||||
.wrap_target
|
||||
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
|
||||
; 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
|
||||
|
||||
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
|
||||
|
||||
pull noblock ; pull value from the FIFO as late as possible
|
||||
out PINS, 8
|
||||
|
||||
; the current time is P0+440ns (P0 + 16ns + 2 clocks (input synchronizers) + 51 instructions)
|
||||
|
||||
wait 0 GPIO, PHI0_GPIO [2] ; wait for PHI0 to fall then hold for 40ns (2 clocks (input synchronizers) + 2-3 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
|
||||
|
||||
irq clear DATA_BUSY_IRQ
|
||||
.wrap
|
97
common/abus-gs-4ns.pio
Normal file
97
common/abus-gs-4ns.pio
Normal file
@ -0,0 +1,97 @@
|
||||
.define public PHI0_GPIO 14
|
||||
.define READ_DATA_TRIGGER_IRQ 4
|
||||
.define DATA_BUSY_IRQ 5
|
||||
|
||||
; Apple II bus interface
|
||||
; Ref: Understanding the Apple II, pages 4-7, 7-8
|
||||
|
||||
.program abus
|
||||
; Prerequisites:
|
||||
; * Bus clock used is PHI0, wired to GPIO 26
|
||||
; * JMP pin is mapped to the R/W signal
|
||||
; * 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 250MHz (4ns/instruction)
|
||||
;
|
||||
; SET bits for tranceiver control:
|
||||
; 0bxxx
|
||||
; x - select AddrHi, active low
|
||||
; x - select AddrLo, active low
|
||||
; 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.
|
||||
in PINS, 8 ; read AddrHi[7:0]
|
||||
set PINS, 0b101 [12] ; enable AddrLo tranceiver and delay for transceiver propagation delay
|
||||
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)
|
||||
|
||||
set PINS, 0b110 [31] ; enable Data tranceiver & wait until both ~DEVSEL and the written data are valid (P0+210ns)
|
||||
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)
|
||||
|
||||
set PINS, 0b110 [4] ; 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 irq DATA_BUSY_IRQ ; wait for the data handling state machine to complete to avoid contention w/transceiver control
|
||||
.wrap
|
||||
|
||||
|
||||
.program abus_device_read
|
||||
; Prerequisites:
|
||||
; * Bus clock used is PHI0, wired to GPIO 26
|
||||
; * JMP pin is the ~DEVSEL signal
|
||||
; * OUT pins are the 8 data signals
|
||||
; * SET pins are the Data transceiver control signals
|
||||
;
|
||||
; SET bits for tranceiver control:
|
||||
; 0bxx
|
||||
; x - select Data transceiver (active low)
|
||||
; x - Data transceiver direction (0=input, 1=output)
|
||||
.wrap_target
|
||||
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
|
||||
; 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
|
||||
|
||||
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]
|
||||
|
||||
pull noblock ; pull value from the FIFO as late as possible [420ns]
|
||||
out PINS, 8 ; [424ns]
|
||||
|
||||
; the current time is P0+424ns (P0 + 10ns + 2 clocks (input synchronizers) + 101 instructions)
|
||||
|
||||
wait 0 GPIO, PHI0_GPIO [7] ; wait for PHI0 to fall then hold for 40ns (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 [P1+56ns]
|
||||
|
||||
irq clear DATA_BUSY_IRQ
|
||||
.wrap
|
97
common/abus-gs-8ns.pio
Normal file
97
common/abus-gs-8ns.pio
Normal file
@ -0,0 +1,97 @@
|
||||
.define public PHI0_GPIO 14
|
||||
.define READ_DATA_TRIGGER_IRQ 4
|
||||
.define DATA_BUSY_IRQ 5
|
||||
|
||||
; Apple II bus interface
|
||||
; Ref: Understanding the Apple II, pages 4-7, 7-8
|
||||
|
||||
.program abus
|
||||
; Prerequisites:
|
||||
; * Bus clock used is PHI0, wired to GPIO 26
|
||||
; * JMP pin is mapped to the R/W signal
|
||||
; * 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)
|
||||
;
|
||||
; SET bits for tranceiver control:
|
||||
; 0bxxx
|
||||
; x - select AddrHi, active low
|
||||
; x - select AddrLo, active low
|
||||
; 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.
|
||||
in PINS, 8 ; read AddrHi[7:0]
|
||||
set PINS, 0b101 [2] ; enable AddrLo tranceiver and delay for transceiver propagation delay
|
||||
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)
|
||||
|
||||
set PINS, 0b110 [15] ; enable Data tranceiver & wait until both ~DEVSEL and the written data are valid (P0+200ns)
|
||||
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+88ns (P0 + 16ns + 2 clocks (input synchronizers) + 7 instructions)
|
||||
|
||||
set PINS, 0b110 ; ensure AddrLo transceiver is disabled and delay for ~DEVSEL to become valid (P0+63ns+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 irq DATA_BUSY_IRQ ; wait for the data handling state machine to complete to avoid contention w/transceiver control
|
||||
.wrap
|
||||
|
||||
|
||||
.program abus_device_read
|
||||
; Prerequisites:
|
||||
; * Bus clock used is PHI0, wired to GPIO 26
|
||||
; * JMP pin is the ~DEVSEL signal
|
||||
; * OUT pins are the 8 data signals
|
||||
; * SET pins are the Data transceiver control signals
|
||||
;
|
||||
; SET bits for tranceiver control:
|
||||
; 0bxx
|
||||
; x - select Data transceiver (active low)
|
||||
; x - Data transceiver direction (0=input, 1=output)
|
||||
.wrap_target
|
||||
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
|
||||
; 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
|
||||
|
||||
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
|
||||
|
||||
pull noblock ; pull value from the FIFO as late as possible
|
||||
out PINS, 8
|
||||
|
||||
; the current time is P0+440ns (P0 + 16ns + 2 clocks (input synchronizers) + 51 instructions)
|
||||
|
||||
wait 0 GPIO, PHI0_GPIO [2] ; wait for PHI0 to fall then hold for 40ns (2 clocks (input synchronizers) + 2-3 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
|
||||
|
||||
irq clear DATA_BUSY_IRQ
|
||||
.wrap
|
95
common/abus.c
Normal file
95
common/abus.c
Normal file
@ -0,0 +1,95 @@
|
||||
#include <string.h>
|
||||
#include <hardware/pio.h>
|
||||
#include "common/config.h"
|
||||
#include "common/abus.h"
|
||||
|
||||
#ifdef OVERCLOCKED
|
||||
#ifdef ANALOG_GS
|
||||
#include "abus-gs-4ns.pio.h"
|
||||
#else
|
||||
#include "abus-4ns.pio.h"
|
||||
#endif
|
||||
#else
|
||||
#ifdef ANALOG_GS
|
||||
#include "abus-gs-8ns.pio.h"
|
||||
#else
|
||||
#include "abus-8ns.pio.h"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if CONFIG_PIN_APPLEBUS_PHI0 != PHI0_GPIO
|
||||
#error CONFIG_PIN_APPLEBUS_PHI0 and PHI0_GPIO must be set to the same pin
|
||||
#endif
|
||||
|
||||
|
||||
static void abus_device_read_setup(PIO pio, uint sm) {
|
||||
uint program_offset = pio_add_program(pio, &abus_device_read_program);
|
||||
pio_sm_claim(pio, sm);
|
||||
|
||||
pio_sm_config c = abus_device_read_program_get_default_config(program_offset);
|
||||
|
||||
// set the "device selected" pin as the jump pin
|
||||
sm_config_set_jmp_pin(&c, CONFIG_PIN_APPLEBUS_DEVSEL);
|
||||
|
||||
// map the OUT pin group to the data signals
|
||||
sm_config_set_out_pins(&c, CONFIG_PIN_APPLEBUS_DATA_BASE, 8);
|
||||
|
||||
// map the SET pin group to the Data transceiver control signals
|
||||
sm_config_set_set_pins(&c, CONFIG_PIN_APPLEBUS_CONTROL_BASE, 2);
|
||||
|
||||
pio_sm_init(pio, sm, program_offset, &c);
|
||||
|
||||
// All the GPIOs are shared and setup by the main program
|
||||
}
|
||||
|
||||
static void abus_main_setup(PIO pio, uint sm) {
|
||||
uint program_offset = pio_add_program(pio, &abus_program);
|
||||
pio_sm_claim(pio, sm);
|
||||
|
||||
pio_sm_config c = abus_program_get_default_config(program_offset);
|
||||
|
||||
// set the bus R/W pin as the jump pin
|
||||
sm_config_set_jmp_pin(&c, CONFIG_PIN_APPLEBUS_RW);
|
||||
|
||||
// map the IN pin group to the data signals
|
||||
sm_config_set_in_pins(&c, CONFIG_PIN_APPLEBUS_DATA_BASE);
|
||||
|
||||
// map the SET pin group to the bus transceiver enable signals
|
||||
sm_config_set_set_pins(&c, CONFIG_PIN_APPLEBUS_CONTROL_BASE+1, 3);
|
||||
|
||||
// configure left shift into ISR & autopush every 26 bits
|
||||
sm_config_set_in_shift(&c, false, true, 26);
|
||||
|
||||
pio_sm_init(pio, sm, program_offset, &c);
|
||||
|
||||
// configure the GPIOs
|
||||
// Ensure all transceivers will start disabled, with Data transceiver direction set to 'in'
|
||||
pio_sm_set_pins_with_mask(pio, sm,
|
||||
(uint32_t)0xe << CONFIG_PIN_APPLEBUS_CONTROL_BASE,
|
||||
(uint32_t)0xf << CONFIG_PIN_APPLEBUS_CONTROL_BASE);
|
||||
pio_sm_set_pindirs_with_mask(pio, sm,
|
||||
(0xf << CONFIG_PIN_APPLEBUS_CONTROL_BASE),
|
||||
(1 << CONFIG_PIN_APPLEBUS_PHI0) | (0xf << CONFIG_PIN_APPLEBUS_CONTROL_BASE) | (0x3ff << CONFIG_PIN_APPLEBUS_DATA_BASE));
|
||||
|
||||
// Disable input synchronization on input pins that are sampled at known stable times
|
||||
// to shave off two clock cycles of input latency
|
||||
pio->input_sync_bypass |= (0x3ff << CONFIG_PIN_APPLEBUS_DATA_BASE);
|
||||
|
||||
pio_gpio_init(pio, CONFIG_PIN_APPLEBUS_PHI0);
|
||||
gpio_set_pulls(CONFIG_PIN_APPLEBUS_PHI0, false, false);
|
||||
for(int pin=CONFIG_PIN_APPLEBUS_CONTROL_BASE; pin < CONFIG_PIN_APPLEBUS_CONTROL_BASE+4; pin++) {
|
||||
pio_gpio_init(pio, pin);
|
||||
}
|
||||
for(int pin=CONFIG_PIN_APPLEBUS_DATA_BASE; pin < CONFIG_PIN_APPLEBUS_DATA_BASE+10; pin++) {
|
||||
pio_gpio_init(pio, pin);
|
||||
gpio_set_pulls(pin, false, false);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void abus_init() {
|
||||
abus_device_read_setup(CONFIG_ABUS_PIO, ABUS_DEVICE_READ_SM);
|
||||
abus_main_setup(CONFIG_ABUS_PIO, ABUS_MAIN_SM);
|
||||
|
||||
pio_enable_sm_mask_in_sync(CONFIG_ABUS_PIO, (1 << ABUS_MAIN_SM) | (1 << ABUS_DEVICE_READ_SM));
|
||||
}
|
13
common/abus.h
Normal file
13
common/abus.h
Normal file
@ -0,0 +1,13 @@
|
||||
#pragma once
|
||||
|
||||
void abus_init();
|
||||
|
||||
#define CARD_SELECT ((value & (1u << CONFIG_PIN_APPLEBUS_DEVSEL-CONFIG_PIN_APPLEBUS_DATA_BASE)) == 0)
|
||||
#define CARD_DEVSEL ((address & 0xcf80) == 0xc080)
|
||||
#define CARD_IOSEL (((address & 0xcf00) >= 0xc100) && ((address & 0xcf00) < 0xc700))
|
||||
#define CARD_IOSTROBE ((address & 0xc800) == 0xc800)
|
||||
|
||||
enum {
|
||||
ABUS_MAIN_SM = 0,
|
||||
ABUS_DEVICE_READ_SM = 1,
|
||||
};
|
97
common/abus.pio
Normal file
97
common/abus.pio
Normal file
@ -0,0 +1,97 @@
|
||||
.define public PHI0_GPIO 26
|
||||
.define READ_DATA_TRIGGER_IRQ 4
|
||||
.define DATA_BUSY_IRQ 5
|
||||
|
||||
; Apple II bus interface
|
||||
; Ref: Understanding the Apple II, pages 4-7, 7-8
|
||||
|
||||
.program abus
|
||||
; Prerequisites:
|
||||
; * Bus clock used is PHI0, wired to GPIO 26
|
||||
; * JMP pin is mapped to the R/W signal
|
||||
; * 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)
|
||||
;
|
||||
; SET bits for tranceiver control:
|
||||
; 0bxxx
|
||||
; x - select AddrHi, active low
|
||||
; x - select AddrLo, active low
|
||||
; 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.
|
||||
in PINS, 8 ; read AddrHi[7:0]
|
||||
set PINS, 0b101 [2] ; enable AddrLo tranceiver and delay for transceiver propagation delay
|
||||
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)
|
||||
|
||||
set PINS, 0b110 [15] ; enable Data tranceiver & wait until both ~DEVSEL and the written data are valid (P0+200ns)
|
||||
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+88ns (P0 + 16ns + 2 clocks (input synchronizers) + 7 instructions)
|
||||
|
||||
set PINS, 0b110 ; ensure AddrLo transceiver is disabled and delay for ~DEVSEL to become valid (P0+63ns+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 irq DATA_BUSY_IRQ ; wait for the data handling state machine to complete to avoid contention w/transceiver control
|
||||
.wrap
|
||||
|
||||
|
||||
.program abus_device_read
|
||||
; Prerequisites:
|
||||
; * Bus clock used is PHI0, wired to GPIO 26
|
||||
; * JMP pin is the ~DEVSEL signal
|
||||
; * OUT pins are the 8 data signals
|
||||
; * SET pins are the Data transceiver control signals
|
||||
;
|
||||
; SET bits for tranceiver control:
|
||||
; 0bxx
|
||||
; x - select Data transceiver (active low)
|
||||
; x - Data transceiver direction (0=input, 1=output)
|
||||
.wrap_target
|
||||
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
|
||||
; 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
|
||||
|
||||
irq set DATA_BUSY_IRQ
|
||||
|
||||
pull noblock ; extra early pull to clear out any standing values from the FIFO
|
||||
|
||||
set PINS, 0b01 ; enable Data tranceiver with output direction
|
||||
mov OSR, ~NULL [3]
|
||||
out PINDIRS, 8 [31] ; set data pins as outputs
|
||||
|
||||
pull noblock ; pull value from the FIFO as late as possible
|
||||
out PINS, 8
|
||||
|
||||
; the current time is P0+440ns (P0 + 16ns + 2 clocks (input synchronizers) + 51 instructions)
|
||||
|
||||
wait 0 GPIO, PHI0_GPIO [2] ; wait for PHI0 to fall then hold for 40ns (2 clocks (input synchronizers) + 2-3 instructions)
|
||||
set PINS, 0b10 ; disable Data tranceiver to tri-state the data bus
|
||||
|
||||
mov OSR, NULL
|
||||
out PINDIRS, 8 ; reset data pins as inputs
|
||||
|
||||
irq clear DATA_BUSY_IRQ
|
||||
.wrap
|
56
common/buffers.c
Normal file
56
common/buffers.c
Normal file
@ -0,0 +1,56 @@
|
||||
#include "buffers.h"
|
||||
|
||||
volatile uint32_t soft_switches = 0;
|
||||
volatile uint32_t internal_flags = 0;
|
||||
|
||||
volatile uint8_t reset_state = 0;
|
||||
|
||||
volatile uint8_t cardslot = 0;
|
||||
volatile uint32_t busactive = 0;
|
||||
|
||||
volatile uint8_t __attribute__((section (".appledata."))) apple_memory[64*1024];
|
||||
volatile uint8_t __attribute__((section (".appledata."))) private_memory[64*1024];
|
||||
|
||||
#ifdef FUNCTION_VGA
|
||||
volatile uint8_t *text_p1 = apple_memory + 0x0400;
|
||||
volatile uint8_t *text_p2 = apple_memory + 0x0800;
|
||||
volatile uint8_t *text_p3 = private_memory + 0x0400;
|
||||
volatile uint8_t *text_p4 = private_memory + 0x0800;
|
||||
volatile uint8_t *hgr_p1 = apple_memory + 0x2000;
|
||||
volatile uint8_t *hgr_p2 = apple_memory + 0x4000;
|
||||
volatile uint8_t *hgr_p3 = private_memory + 0x2000;
|
||||
volatile uint8_t *hgr_p4 = private_memory + 0x4000;
|
||||
#endif
|
||||
|
||||
volatile uint8_t *baseio = apple_memory + 0xc000;
|
||||
volatile uint8_t *slotio = apple_memory + 0xc080;
|
||||
volatile uint8_t *slotrom = apple_memory + 0xc100;
|
||||
volatile uint8_t *extdrom = apple_memory + 0xc800;
|
||||
|
||||
/* Slot 1: Grapper */
|
||||
volatile uint8_t *slot1io = apple_memory + 0xc090;
|
||||
volatile uint8_t *slot1rom = apple_memory + 0xc100;
|
||||
|
||||
/* Slot 2: Super Serial Card */
|
||||
volatile uint8_t *slot2io = apple_memory + 0xc0a0;
|
||||
volatile uint8_t *slot2rom = apple_memory + 0xc200;
|
||||
|
||||
/* Slot 3: 80 Column Card */
|
||||
volatile uint8_t *slot3io = apple_memory + 0xc0b0;
|
||||
volatile uint8_t *slot3rom = apple_memory + 0xc300;
|
||||
|
||||
/* Slot 4: PCPI Applicard */
|
||||
volatile uint8_t *slot4io = apple_memory + 0xc0c0;
|
||||
volatile uint8_t *slot4rom = apple_memory + 0xc400;
|
||||
|
||||
/* Slot 5: Uthernet */
|
||||
volatile uint8_t *slot5io = apple_memory + 0xc0d0;
|
||||
volatile uint8_t *slot5rom = apple_memory + 0xc500;
|
||||
|
||||
/* Slot 6: Disk II */
|
||||
volatile uint8_t *slot6io = apple_memory + 0xc0e0;
|
||||
volatile uint8_t *slot6rom = apple_memory + 0xc600;
|
||||
|
||||
/* Slot 7: ProDOS ROM Disk */
|
||||
volatile uint8_t *slot7io = apple_memory + 0xc0f0;
|
||||
volatile uint8_t *slot7rom = apple_memory + 0xc700;
|
111
common/buffers.h
Normal file
111
common/buffers.h
Normal file
@ -0,0 +1,111 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
extern volatile uint8_t reset_state;
|
||||
|
||||
extern volatile uint8_t cardslot;
|
||||
extern volatile uint32_t busactive;
|
||||
|
||||
extern volatile uint8_t apple_memory[64*1024];
|
||||
extern volatile uint8_t private_memory[64*1024];
|
||||
|
||||
extern volatile uint16_t cfptr;
|
||||
extern volatile uint8_t cfbuf[4096];
|
||||
|
||||
#define config_cmdbuf ((uint8_t*)(apple_memory+0xC0F0+(cardslot<<8)))
|
||||
#define config_rpybuf ((uint8_t*)(apple_memory+0xC0F8+(cardslot<<8)))
|
||||
|
||||
#ifdef FUNCTION_VGA
|
||||
extern volatile uint8_t *text_p1;
|
||||
extern volatile uint8_t *text_p2;
|
||||
extern volatile uint8_t *text_p3;
|
||||
extern volatile uint8_t *text_p4;
|
||||
extern volatile uint8_t *hgr_p1;
|
||||
extern volatile uint8_t *hgr_p2;
|
||||
extern volatile uint8_t *hgr_p3;
|
||||
extern volatile uint8_t *hgr_p4;
|
||||
|
||||
/* Videx VideoTerm */
|
||||
extern volatile uint8_t *videx_page;
|
||||
|
||||
#endif
|
||||
|
||||
extern volatile uint8_t *baseio;
|
||||
extern volatile uint8_t *slotio;
|
||||
extern volatile uint8_t *slotrom;
|
||||
extern volatile uint8_t *extdrom;
|
||||
|
||||
/* Slot 1: Grapper */
|
||||
extern volatile uint8_t *slot1io;
|
||||
extern volatile uint8_t *slot1rom;
|
||||
|
||||
/* Slot 2: Super Serial Card */
|
||||
extern volatile uint8_t *slot2io;
|
||||
extern volatile uint8_t *slot2rom;
|
||||
|
||||
/* Slot 3: 80 Column Card */
|
||||
extern volatile uint8_t *slot3io;
|
||||
extern volatile uint8_t *slot3rom;
|
||||
|
||||
/* Slot 4: PCPI Applicard */
|
||||
extern volatile uint8_t *slot4io;
|
||||
extern volatile uint8_t *slot4rom;
|
||||
|
||||
/* Slot 5: Uthernet */
|
||||
extern volatile uint8_t *slot5io;
|
||||
extern volatile uint8_t *slot5rom;
|
||||
|
||||
/* Slot 6: Disk II */
|
||||
extern volatile uint8_t *slot6io;
|
||||
extern volatile uint8_t *slot6rom;
|
||||
|
||||
/* Slot 7: ProDOS ROM Disk */
|
||||
extern volatile uint8_t *slot7io;
|
||||
extern volatile uint8_t *slot7rom;
|
||||
|
||||
extern volatile uint32_t soft_switches;
|
||||
|
||||
extern volatile uint32_t internal_flags;
|
||||
|
||||
#define SOFTSW_TEXT_MODE 0x00000001
|
||||
#define SOFTSW_MIX_MODE 0x00000002
|
||||
#define SOFTSW_HIRES_MODE 0x00000004
|
||||
#define SOFTSW_MODE_MASK 0x00000007
|
||||
#define SOFTSW_PAGE_2 0x00000008
|
||||
|
||||
// Apple IIe/c/gs softswitches
|
||||
#define SOFTSW_80STORE 0x00000100
|
||||
#define SOFTSW_AUX_READ 0x00000200
|
||||
#define SOFTSW_AUX_WRITE 0x00000400
|
||||
#define SOFTSW_AUXZP 0x00000800
|
||||
#define SOFTSW_SLOT3ROM 0x00001000
|
||||
#define SOFTSW_80COL 0x00002000
|
||||
#define SOFTSW_ALTCHAR 0x00004000
|
||||
#define SOFTSW_DGR 0x00008000
|
||||
|
||||
#define SOFTSW_NEWVID_MASK 0xE0
|
||||
#define SOFTSW_NEWVID_SHIFT 11
|
||||
|
||||
#define SOFTSW_MONOCHROME 0x00010000
|
||||
#define SOFTSW_LINEARIZE 0x00020000
|
||||
#define SOFTSW_SHR 0x00040000
|
||||
|
||||
#define SOFTSW_IOUDIS 0x00080000
|
||||
|
||||
#define SOFTSW_SHADOW_MASK 0x7F
|
||||
#define SOFTSW_SHADOW_SHIFT 20
|
||||
|
||||
#define SOFTSW_SHADOW_TEXT 0x00100000
|
||||
#define SOFTSW_SHADOW_HGR1 0x00200000
|
||||
#define SOFTSW_SHADOW_HGR2 0x00400000
|
||||
#define SOFTSW_SHADOW_SHR 0x00800000
|
||||
#define SOFTSW_SHADOW_AUXHGR 0x01000000
|
||||
#define SOFTSW_SHADOW_ALTDISP 0x02000000
|
||||
#define SOFTSW_SHADOW_IO 0x04000000
|
||||
|
||||
// V2 Analog specific softswitches
|
||||
#define SOFTSW_TERMINAL 0x10000000
|
||||
#define IFLAGS_TEST 0x20000000
|
||||
#define IFLAGS_IIE_REGS 0x40000000
|
||||
#define IFLAGS_IIGS_REGS 0x80000000
|
4
common/build.h
Normal file
4
common/build.h
Normal file
@ -0,0 +1,4 @@
|
||||
#define BUILDDATE 0x20230403
|
||||
#define BUILDID 0x0171
|
||||
#define BUILDSTR " 3 Apr 2023 Build 0171"
|
||||
|
54
common/cfgtoken.h
Normal file
54
common/cfgtoken.h
Normal file
@ -0,0 +1,54 @@
|
||||
|
||||
#define NEWCONFIG_MAGIC 0x0001434E // "NC\x01\x00"
|
||||
#define NEWCONFIG_EOF_MARKER 0x00464F45 // "EOF\x00"
|
||||
#define CFGTOKEN_REVISION 0x0001434E // "RV\xXX\x00"
|
||||
|
||||
#define CFGTOKEN_MODE_VGA 0x0000564D // "MV\x00\x00" VGA
|
||||
#define CFGTOKEN_MODE_PCPI 0x00005A4D // "MZ\x00\x00" PCPI Applicard
|
||||
#define CFGTOKEN_MODE_SER 0x0000534D // "MS\x00\x00" Serial
|
||||
#define CFGTOKEN_MODE_PAR 0x0000504D // "MP\x00\x00" Parallel
|
||||
#define CFGTOKEN_MODE_SNES 0x0000474D // "MG\x00\x00" SNESMAX
|
||||
#define CFGTOKEN_MODE_NET 0x0000454D // "ME\x00\x00" Ethernet
|
||||
#define CFGTOKEN_MODE_FILE 0x0000464D // "MF\x00\x00" Filesystem
|
||||
|
||||
#define CFGTOKEN_HOST_AUTO 0x00004148 // "HA\x00\x00" Autodetect
|
||||
#define CFGTOKEN_HOST_II 0x00003248 // "H2\x00\x00" II/II+
|
||||
#define CFGTOKEN_HOST_IIE 0x00004548 // "HE\x00\x00" IIe
|
||||
#define CFGTOKEN_HOST_IIGS 0x00004748 // "HG\x00\x00" IIgs
|
||||
#define CFGTOKEN_HOST_PRAVETZ 0x00005048 // "HP\x00\x00" Pravetz
|
||||
#define CFGTOKEN_HOST_BASIS 0x00004248 // "HB\x00\x00" Basis 108
|
||||
|
||||
#define CFGTOKEN_MUX_LOOP 0x00004C53 // "SL\x00\x00" Serial Loopback
|
||||
#define CFGTOKEN_MUX_USB 0x00005553 // "SU\x00\x00" USB CDC
|
||||
#define CFGTOKEN_MUX_WIFI 0x00005753 // "SW\x00\x00" WiFi Modem
|
||||
#define CFGTOKEN_MUX_PRN 0x00005053 // "SP\x00\x00" WiFi Printer
|
||||
#define CFGTOKEN_SER_BAUD 0x02004253 // "SB\x00\x01" Serial Baudrate Divisor
|
||||
|
||||
#define CFGTOKEN_USB_HOST 0x00004855 // "UH\x00\x00" USB CDC Host
|
||||
#define CFGTOKEN_USB_GUEST 0x00004755 // "UG\x00\x00" USB CDC Guest Device
|
||||
#define CFGTOKEN_USB_MIDI 0x00004D55 // "UM\x00\x00" USB MIDI Guest Device
|
||||
|
||||
#define CFGTOKEN_WIFI_AP 0x00004157 // "WA\x00\x00" WiFi AP
|
||||
#define CFGTOKEN_WIFI_CL 0x00004357 // "WC\x00\x00" WiFi Client
|
||||
|
||||
#define CFGTOKEN_WIFI_SSID 0x00005357 // "WS\x00\xSS" WiFi SSID
|
||||
#define CFGTOKEN_WIFI_PSK 0x00005057 // "WP\x00\xSS" WiFi PSK
|
||||
|
||||
#define CFGTOKEN_WIFI_IP 0x04004957 // "WI\x00\xSS" WiFi IP
|
||||
#define CFGTOKEN_WIFI_NM 0x04004E57 // "WN\x00\xSS" WiFi Netmask
|
||||
|
||||
#define CFGTOKEN_JD_HOST 0x0000484A // "JH\x00\x01" JetDirect Hostname
|
||||
#define CFGTOKEN_JD_PORT 0x0200444A // "JD\x00\x01" JetDirect Port
|
||||
|
||||
#define CFGTOKEN_MONO_00 0x00005056 // "VP\x00\x00" Full Color Video
|
||||
#define CFGTOKEN_MONO_80 0x00805056 // "VP\x80\x00" B&W Video
|
||||
#define CFGTOKEN_MONO_90 0x00905056 // "VP\x90\x00" B&W Inverse
|
||||
#define CFGTOKEN_MONO_A0 0x00A05056 // "VP\xA0\x00" Amber
|
||||
#define CFGTOKEN_MONO_B0 0x00B05056 // "VP\xB0\x00" Amber Inverse
|
||||
#define CFGTOKEN_MONO_C0 0x00C05056 // "VP\xC0\x00" Green
|
||||
#define CFGTOKEN_MONO_D0 0x00D05056 // "VP\xD0\x00" Green Inverse
|
||||
#define CFGTOKEN_MONO_E0 0x00E05056 // "VP\xE0\x00" C64
|
||||
#define CFGTOKEN_MONO_F0 0x00F05056 // "VP\xF0\x00" Custom
|
||||
|
||||
#define CFGTOKEN_TBCOLOR 0x00005456 // "VT\xXX\x00" Custom default TBCOLOR
|
||||
#define CFGTOKEN_BORDER 0x00004256 // "VB\xXX\x00" Custom default BORDER
|
627
common/config.c
Normal file
627
common/config.c
Normal file
@ -0,0 +1,627 @@
|
||||
#include "common/config.h"
|
||||
#include "common/buffers.h"
|
||||
#include "common/flash.h"
|
||||
#include "common/build.h"
|
||||
#include "common/dmacopy.h"
|
||||
#include "vga/render.h"
|
||||
#include "vga/vgaout.h"
|
||||
#include <string.h>
|
||||
|
||||
volatile compat_t cfg_machine = MACHINE_AUTO;
|
||||
volatile compat_t current_machine = MACHINE_AUTO;
|
||||
|
||||
#ifdef FUNCTION_Z80
|
||||
volatile usbmux_t usbmux;
|
||||
volatile serialmux_t serialmux;
|
||||
volatile wifimode_t wifimode;
|
||||
|
||||
volatile uint8_t wifi_ssid[32];
|
||||
volatile uint8_t wifi_psk[32];
|
||||
#endif
|
||||
|
||||
#ifdef FUNCTION_VGA
|
||||
extern volatile bool userfont;
|
||||
extern uint8_t character_rom[4096];
|
||||
extern uint8_t terminal_character_rom[4096];
|
||||
#endif
|
||||
|
||||
extern volatile bool businterface_hold;
|
||||
extern volatile bool businterface_lockout;
|
||||
|
||||
volatile uint16_t cfptr = 0;
|
||||
volatile uint8_t cfbuf[4096];
|
||||
|
||||
uint32_t config_temp[1024];
|
||||
|
||||
#define REPLY_OK 0x00
|
||||
#define REPLY_BUSY 0xBB
|
||||
#define REPLY_EOF 0x01
|
||||
#define REPLY_NOFILE 0x02
|
||||
#define REPLY_EPARAM 0x03
|
||||
#define REPLY_ECMD 0x04
|
||||
|
||||
bool DELAYED_COPY_CODE(parse_config)(uint32_t address) {
|
||||
uint32_t *config = (uint32_t*)address;
|
||||
int i = 0;
|
||||
|
||||
if(config[0] != NEWCONFIG_MAGIC) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for(i = 0; i < (CONFIG_SIZE/sizeof(uint32_t)); i++) {
|
||||
if(config[i] == NEWCONFIG_EOF_MARKER) return true;
|
||||
|
||||
switch(config[i] & 0x0000FFFF) {
|
||||
case CFGTOKEN_HOST_AUTO:
|
||||
cfg_machine = MACHINE_AUTO;
|
||||
break;
|
||||
case CFGTOKEN_HOST_II:
|
||||
cfg_machine = MACHINE_II;
|
||||
break;
|
||||
case CFGTOKEN_HOST_IIE:
|
||||
cfg_machine = MACHINE_IIE;
|
||||
break;
|
||||
case CFGTOKEN_HOST_IIGS:
|
||||
cfg_machine = MACHINE_IIGS;
|
||||
break;
|
||||
case CFGTOKEN_HOST_PRAVETZ:
|
||||
cfg_machine = MACHINE_PRAVETZ;
|
||||
break;
|
||||
#ifdef FUNCTION_VGA
|
||||
case CFGTOKEN_MONO_00:
|
||||
mono_palette = (config[i] >> 16) & 0xF;
|
||||
break;
|
||||
case CFGTOKEN_TBCOLOR:
|
||||
terminal_tbcolor = (config[i] >> 16) & 0xFF;
|
||||
break;
|
||||
case CFGTOKEN_BORDER:
|
||||
terminal_border = (config[i] >> 16) & 0xF;
|
||||
break;
|
||||
#else
|
||||
case CFGTOKEN_MUX_LOOP:
|
||||
serialmux = SERIAL_LOOP;
|
||||
break;
|
||||
case CFGTOKEN_MUX_USB:
|
||||
serialmux = SERIAL_USB;
|
||||
break;
|
||||
case CFGTOKEN_MUX_WIFI:
|
||||
serialmux = SERIAL_WIFI;
|
||||
break;
|
||||
case CFGTOKEN_MUX_PRN:
|
||||
serialmux = SERIAL_PRINTER;
|
||||
break;
|
||||
case CFGTOKEN_SER_BAUD:
|
||||
//baud = config[i+1];
|
||||
break;
|
||||
case CFGTOKEN_USB_HOST:
|
||||
usbmux = USB_HOST_CDC;
|
||||
break;
|
||||
case CFGTOKEN_USB_GUEST:
|
||||
usbmux = USB_GUEST_CDC;
|
||||
break;
|
||||
// case CFGTOKEN_USB_MIDI:
|
||||
// usbmux = USB_GUEST_MIDI;
|
||||
// break;
|
||||
case CFGTOKEN_WIFI_AP:
|
||||
wifimode = WIFI_AP;
|
||||
break;
|
||||
case CFGTOKEN_WIFI_CL:
|
||||
wifimode = WIFI_CLIENT;
|
||||
break;
|
||||
case CFGTOKEN_WIFI_SSID:
|
||||
// memset((char*)wifi_ssid, 0, sizeof(wifi_ssid));
|
||||
// strncpy((char*)wifi_ssid, (char*)(config+i+1), (config[i] >> 24));
|
||||
break;
|
||||
case CFGTOKEN_WIFI_PSK:
|
||||
// memset((char*)wifi_psk, 0, sizeof(wifi_psk));
|
||||
// strncpy((char*)wifi_psk, (char*)(config+i+1), (config[i] >> 24));
|
||||
break;
|
||||
case CFGTOKEN_WIFI_IP:
|
||||
// wifi_address = config[i+1];
|
||||
break;
|
||||
case CFGTOKEN_WIFI_NM:
|
||||
// wifi_netmask = config[i+1];
|
||||
break;
|
||||
case CFGTOKEN_JD_HOST:
|
||||
// memset((uint8_t*)jd_host, 0, sizeof(jd_host));
|
||||
// strncpy(jd_host, (char*)(config+i+1), (config[i] >> 24));
|
||||
break;
|
||||
case CFGTOKEN_JD_PORT:
|
||||
// jd_port = config[i+1];
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
|
||||
// Advance by the number of dwords for this token
|
||||
i += (((config[i] >> 24) + 3) >> 2);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void DELAYED_COPY_CODE(default_config)() {
|
||||
#ifdef FUNCTION_Z80
|
||||
serialmux = SERIAL_LOOP;
|
||||
usbmux = USB_GUEST_CDC;
|
||||
wifimode = WIFI_AP;
|
||||
strcpy((char*)wifi_ssid, "V2RetroNet");
|
||||
strcpy((char*)wifi_psk, "Analog");
|
||||
#endif
|
||||
cfg_machine = MACHINE_AUTO;
|
||||
}
|
||||
|
||||
int DELAYED_COPY_CODE(make_config)(uint8_t rev) {
|
||||
int i = 0;
|
||||
|
||||
memset(config_temp, 0, sizeof(config_temp));
|
||||
|
||||
config_temp[i++] = NEWCONFIG_MAGIC;
|
||||
config_temp[i++] = CFGTOKEN_REVISION | (((uint16_t)rev) << 16);
|
||||
|
||||
switch(cfg_machine) {
|
||||
default:
|
||||
case MACHINE_AUTO:
|
||||
config_temp[i++] = CFGTOKEN_HOST_AUTO;
|
||||
break;
|
||||
case MACHINE_II:
|
||||
config_temp[i++] = CFGTOKEN_HOST_II;
|
||||
break;
|
||||
case MACHINE_IIE:
|
||||
config_temp[i++] = CFGTOKEN_HOST_IIE;
|
||||
break;
|
||||
case MACHINE_IIGS:
|
||||
config_temp[i++] = CFGTOKEN_HOST_IIGS;
|
||||
break;
|
||||
}
|
||||
#ifdef FUNCTION_Z80
|
||||
switch(serialmux) {
|
||||
case SERIAL_USB:
|
||||
config_temp[i++] = CFGTOKEN_MUX_USB;
|
||||
break;
|
||||
case SERIAL_WIFI:
|
||||
config_temp[i++] = CFGTOKEN_MUX_WIFI;
|
||||
break;
|
||||
case SERIAL_PRINTER:
|
||||
config_temp[i++] = CFGTOKEN_MUX_PRN;
|
||||
break;
|
||||
default:
|
||||
case SERIAL_LOOP:
|
||||
config_temp[i++] = CFGTOKEN_MUX_LOOP;
|
||||
break;
|
||||
}
|
||||
switch(usbmux) {
|
||||
case USB_HOST_CDC:
|
||||
config_temp[i++] = CFGTOKEN_USB_HOST;
|
||||
break;
|
||||
default:
|
||||
case USB_GUEST_CDC:
|
||||
config_temp[i++] = CFGTOKEN_USB_GUEST;
|
||||
break;
|
||||
case USB_GUEST_MIDI:
|
||||
config_temp[i++] = CFGTOKEN_USB_MIDI;
|
||||
break;
|
||||
}
|
||||
|
||||
switch(wifimode) {
|
||||
case WIFI_CLIENT:
|
||||
config_temp[i++] = CFGTOKEN_WIFI_AP;
|
||||
break;
|
||||
case WIFI_AP:
|
||||
config_temp[i++] = CFGTOKEN_WIFI_CL;
|
||||
break;
|
||||
}
|
||||
|
||||
config_temp[i] = CFGTOKEN_WIFI_SSID | (((uint32_t)strlen((char*)wifi_ssid)+1) << 24);
|
||||
strcpy((char*)(config_temp+i+1), (char*)wifi_ssid);
|
||||
i += 1 + (((config_temp[i] >> 24) + 3) >> 2);
|
||||
|
||||
config_temp[i] = CFGTOKEN_WIFI_PSK | (((uint32_t)strlen((char*)wifi_psk)+1) << 24);
|
||||
strcpy((char*)(config_temp+i+1), (char*)wifi_psk);
|
||||
i += 1 + (((config_temp[i] >> 24) + 3) >> 2);
|
||||
#endif
|
||||
|
||||
#ifdef FUNCTION_VGA
|
||||
config_temp[i++] = CFGTOKEN_MONO_00 | ((mono_palette & 0xF) << 20);
|
||||
config_temp[i++] = CFGTOKEN_TBCOLOR | ((terminal_tbcolor & 0xFF) << 16);
|
||||
config_temp[i++] = CFGTOKEN_BORDER | ((terminal_border & 0xF) << 16);
|
||||
|
||||
// TODO: Font
|
||||
//config_temp[i++] = CFGTOKEN_FONTSLOT | ((terminal_font & 0x1F) << 16);
|
||||
#endif
|
||||
config_temp[i++] = NEWCONFIG_EOF_MARKER;
|
||||
|
||||
return i * 4;
|
||||
}
|
||||
|
||||
// Verify config block starts with the appropriate magic, has an end marker,
|
||||
// and doesn't have any fields that would overflow the block.
|
||||
bool DELAYED_COPY_CODE(is_config_valid)(uint32_t address) {
|
||||
uint32_t *config = (uint32_t*)address;
|
||||
int i;
|
||||
|
||||
if(config[0] != NEWCONFIG_MAGIC) return false;
|
||||
|
||||
for(i = 0; i < (CONFIG_SIZE/sizeof(uint32_t)); i++) {
|
||||
if(config[i] == NEWCONFIG_EOF_MARKER) return true;
|
||||
|
||||
i += ((config[i] >> 24) + 3) >> 2;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Find and return the config revision number for the block
|
||||
uint8_t DELAYED_COPY_CODE(get_config_rev)(uint32_t address) {
|
||||
uint32_t *config = (uint32_t*)address;
|
||||
int i;
|
||||
|
||||
for(i = 0; i < (CONFIG_SIZE/sizeof(uint32_t)); i++) {
|
||||
if((config[i] & 0x0000FFFF) == CFGTOKEN_REVISION)
|
||||
return (config[i] >> 16) & 0xFF;
|
||||
|
||||
if(config[i] == NEWCONFIG_EOF_MARKER) return 0x00;
|
||||
|
||||
i += ((config[i] >> 24) + 3) >> 2;
|
||||
}
|
||||
|
||||
return 0x00;
|
||||
}
|
||||
|
||||
// Every time we write the config we overwrite the older slot,
|
||||
// ensuring we don't leave the user without a configuration.
|
||||
// We increment the revision number each time, wrapping back to 0x00 from 0xFF.
|
||||
bool DELAYED_COPY_CODE(is_primary_config_newer)() {
|
||||
uint8_t a=get_config_rev(FLASH_CONFIG_PRIMARY);
|
||||
uint8_t b=get_config_rev(FLASH_CONFIG_SECONDARY);
|
||||
|
||||
return (a == ((b+1) & 0xff));
|
||||
}
|
||||
|
||||
bool DELAYED_COPY_CODE(read_config)() {
|
||||
if(is_config_valid(FLASH_CONFIG_ONETIME)) {
|
||||
internal_flags &= ~IFLAGS_TEST;
|
||||
soft_switches |= SOFTSW_TEXT_MODE;
|
||||
if(parse_config(FLASH_CONFIG_ONETIME))
|
||||
return true;
|
||||
}
|
||||
if(is_config_valid(FLASH_CONFIG_PRIMARY)) {
|
||||
if(!is_config_valid(FLASH_CONFIG_SECONDARY) || (is_primary_config_newer())) {
|
||||
if(parse_config(FLASH_CONFIG_PRIMARY))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if(is_config_valid(FLASH_CONFIG_SECONDARY)) {
|
||||
if(parse_config(FLASH_CONFIG_SECONDARY))
|
||||
return true;
|
||||
}
|
||||
|
||||
default_config();
|
||||
return false;
|
||||
}
|
||||
|
||||
bool DELAYED_COPY_CODE(write_config)(bool onetime) {
|
||||
uint8_t rev = 0xFF;
|
||||
bool write_secondary = false;
|
||||
bool retval = false;
|
||||
|
||||
// Disable video output to stop DMA and IRQs
|
||||
vga_dpms_sleep();
|
||||
|
||||
if(is_config_valid(FLASH_CONFIG_PRIMARY) && is_config_valid(FLASH_CONFIG_SECONDARY)) {
|
||||
write_secondary = is_primary_config_newer();
|
||||
rev = write_secondary ? get_config_rev(FLASH_CONFIG_PRIMARY) : get_config_rev(FLASH_CONFIG_SECONDARY);
|
||||
} else if(is_config_valid(FLASH_CONFIG_PRIMARY)) {
|
||||
write_secondary = true;
|
||||
rev = get_config_rev(FLASH_CONFIG_PRIMARY);
|
||||
} else if(is_config_valid(FLASH_CONFIG_SECONDARY)) {
|
||||
write_secondary = false;
|
||||
rev = get_config_rev(FLASH_CONFIG_SECONDARY);
|
||||
}
|
||||
|
||||
if(make_config(rev + 1) <= CONFIG_SIZE) {
|
||||
|
||||
if(onetime) {
|
||||
flash_range_erase((FLASH_CONFIG_ONETIME-XIP_BASE), CONFIG_SIZE);
|
||||
flash_range_program((FLASH_CONFIG_ONETIME-XIP_BASE), (const uint8_t *)config_temp, CONFIG_SIZE);
|
||||
} else if(write_secondary) {
|
||||
flash_range_erase((FLASH_CONFIG_SECONDARY-XIP_BASE), CONFIG_SIZE);
|
||||
flash_range_program((FLASH_CONFIG_SECONDARY-XIP_BASE), (const uint8_t *)config_temp, CONFIG_SIZE);
|
||||
} else {
|
||||
flash_range_erase((FLASH_CONFIG_PRIMARY-XIP_BASE), CONFIG_SIZE);
|
||||
flash_range_program((FLASH_CONFIG_PRIMARY-XIP_BASE), (const uint8_t *)config_temp, CONFIG_SIZE);
|
||||
}
|
||||
|
||||
retval = true;
|
||||
}
|
||||
|
||||
// Enable video output now that we are done
|
||||
vga_dpms_wake();
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
#ifdef FUNCTION_VGA
|
||||
uint8_t DELAYED_COPY_CODE(test_font)(uint16_t param0) {
|
||||
int i;
|
||||
|
||||
for(i = 0; i < 4096; i++) {
|
||||
character_rom[i] = apple_memory[param0+i];
|
||||
}
|
||||
|
||||
return REPLY_OK;
|
||||
}
|
||||
|
||||
uint8_t DELAYED_COPY_CODE(write_font)(uint16_t param0, uint16_t param1) {
|
||||
int i;
|
||||
|
||||
if(param1 > 0x27) return REPLY_EPARAM;
|
||||
|
||||
// Disable video output to stop DMA and IRQs
|
||||
vga_dpms_sleep();
|
||||
|
||||
for(i = 0; i < 4096; i++) {
|
||||
character_rom[i] = apple_memory[param0+i];
|
||||
}
|
||||
|
||||
flash_range_erase((FLASH_FONT(param1)-XIP_BASE), FONT_SIZE);
|
||||
flash_range_program((FLASH_FONT(param1)-XIP_BASE), character_rom, FONT_SIZE);
|
||||
|
||||
// Enable video output now that we are done
|
||||
vga_dpms_wake();
|
||||
|
||||
return REPLY_OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
uint8_t DELAYED_COPY_CODE(cf_readblock)(uint16_t param0) {
|
||||
if(param0 >= (FLASH_SIZE/4096)) return REPLY_EPARAM;
|
||||
|
||||
// Disable video output to stop DMA and IRQs
|
||||
vga_dpms_sleep();
|
||||
|
||||
memcpy32(cfbuf, XIP_BASE+(param0 * 4096), 4096);
|
||||
|
||||
// Enable video output now that we are done
|
||||
vga_dpms_wake();
|
||||
|
||||
return REPLY_OK;
|
||||
}
|
||||
|
||||
uint8_t DELAYED_COPY_CODE(cf_writeblock)(uint16_t param0) {
|
||||
// Protect bottom 512K of flash
|
||||
if(param0 < 0x080)
|
||||
return REPLY_EPARAM;
|
||||
|
||||
if(param0 >= (FLASH_SIZE/4096))
|
||||
return REPLY_EPARAM;
|
||||
|
||||
// Disable video output to stop DMA and IRQs
|
||||
vga_dpms_sleep();
|
||||
|
||||
flash_range_program(param0 * 4096, (void*)cfbuf, 4096);
|
||||
|
||||
// Enable video output now that we are done
|
||||
vga_dpms_wake();
|
||||
|
||||
return REPLY_OK;
|
||||
}
|
||||
|
||||
uint8_t DELAYED_COPY_CODE(cf_eraseblock)(uint16_t param0) {
|
||||
// Protect bottom 512K of flash
|
||||
if(param0 < 0x080)
|
||||
return REPLY_EPARAM;
|
||||
|
||||
if(param0 >= (FLASH_SIZE/4096))
|
||||
return REPLY_EPARAM;
|
||||
|
||||
// Disable video output to stop DMA and IRQs
|
||||
vga_dpms_sleep();
|
||||
|
||||
flash_range_erase(param0 * 4096, 4096);
|
||||
|
||||
// Enable video output now that we are done
|
||||
vga_dpms_wake();
|
||||
|
||||
return REPLY_OK;
|
||||
}
|
||||
|
||||
void DELAYED_COPY_CODE(config_handler)() {
|
||||
uint8_t retval = 0;
|
||||
uint16_t param0, param1, param2;
|
||||
int rs = 1;
|
||||
|
||||
if(config_cmdbuf[0] == 0xFF) return;
|
||||
|
||||
param0 = config_cmdbuf[3];
|
||||
param0 <<= 8;
|
||||
param0 |= config_cmdbuf[2];
|
||||
|
||||
param1 = config_cmdbuf[5];
|
||||
param1 <<= 8;
|
||||
param1 |= config_cmdbuf[4];
|
||||
|
||||
param2 = config_cmdbuf[7];
|
||||
param2 <<= 8;
|
||||
param2 |= config_cmdbuf[6];
|
||||
|
||||
config_rpybuf[7] = 0x00;
|
||||
config_rpybuf[6] = 0x00;
|
||||
config_rpybuf[5] = 0x00;
|
||||
config_rpybuf[4] = 0x00;
|
||||
config_rpybuf[3] = 0x00;
|
||||
config_rpybuf[2] = 0x00;
|
||||
config_rpybuf[1] = 0x00;
|
||||
config_rpybuf[0] = REPLY_BUSY;
|
||||
|
||||
switch(config_cmdbuf[0]) {
|
||||
#ifdef FUNCTION_VGA
|
||||
case 'C':
|
||||
switch(config_cmdbuf[1]) {
|
||||
default:
|
||||
retval = REPLY_ECMD;
|
||||
break;
|
||||
case 'T':
|
||||
// One-time load of font data (lost at reboot)
|
||||
retval = test_font(param0);
|
||||
case 'I':
|
||||
// Save font to flash
|
||||
retval = write_font(param0, param1);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
case 'H':
|
||||
retval = REPLY_OK;
|
||||
switch(config_cmdbuf[1]) {
|
||||
default:
|
||||
retval = REPLY_ECMD;
|
||||
break;
|
||||
case '2':
|
||||
current_machine = MACHINE_II;
|
||||
internal_flags &= ~(IFLAGS_IIE_REGS | IFLAGS_IIGS_REGS);
|
||||
break;
|
||||
case 'E':
|
||||
current_machine = MACHINE_IIE;
|
||||
internal_flags &= ~IFLAGS_IIGS_REGS;
|
||||
internal_flags |= IFLAGS_IIE_REGS;
|
||||
break;
|
||||
case 'G':
|
||||
current_machine = MACHINE_IIGS;
|
||||
internal_flags |= IFLAGS_IIE_REGS | IFLAGS_IIGS_REGS;
|
||||
break;
|
||||
#if 0
|
||||
case 'B':
|
||||
current_machine = MACHINE_BASIS;
|
||||
internal_flags &= ~(IFLAGS_IIE_REGS | IFLAGS_IIGS_REGS);
|
||||
break;
|
||||
case 'P':
|
||||
current_machine = MACHINE_PRAVETZ;
|
||||
internal_flags &= ~(IFLAGS_IIE_REGS | IFLAGS_IIGS_REGS);
|
||||
break;
|
||||
case '7':
|
||||
current_machine = MACHINE_AGAT7;
|
||||
internal_flags &= ~(IFLAGS_IIE_REGS | IFLAGS_IIGS_REGS);
|
||||
break;
|
||||
case '9':
|
||||
current_machine = MACHINE_AGAT9;
|
||||
internal_flags &= ~(IFLAGS_IIE_REGS | IFLAGS_IIGS_REGS);
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
|
||||
case 'f':
|
||||
// Flash Commands
|
||||
// All valid flash commands will reset the cf pointer to 0
|
||||
switch(config_cmdbuf[1]) {
|
||||
default:
|
||||
retval = REPLY_ECMD;
|
||||
break;
|
||||
case 'r':
|
||||
// Read block
|
||||
retval = cf_readblock(param0);
|
||||
cfptr = 0;
|
||||
break;
|
||||
case 'w':
|
||||
// Write block
|
||||
retval = cf_writeblock(param0);
|
||||
cfptr = 0;
|
||||
break;
|
||||
case 'e':
|
||||
// Erase block
|
||||
retval = cf_eraseblock(param0);
|
||||
cfptr = 0;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'R':
|
||||
// Reboot and bypass auto-detection of machine type.
|
||||
cfg_machine = current_machine;
|
||||
write_config(true);
|
||||
flash_reboot();
|
||||
break;
|
||||
|
||||
case 'I':
|
||||
switch(config_cmdbuf[1]) {
|
||||
default:
|
||||
retval = REPLY_ECMD;
|
||||
break;
|
||||
case 'H':
|
||||
// Identify Current Host Setting
|
||||
retval = REPLY_OK;
|
||||
switch(current_machine) {
|
||||
case MACHINE_II:
|
||||
config_rpybuf[rs++] = '2';
|
||||
break;
|
||||
case MACHINE_IIE:
|
||||
config_rpybuf[rs++] = 'E';
|
||||
break;
|
||||
case MACHINE_IIGS:
|
||||
config_rpybuf[rs++] = 'G';
|
||||
break;
|
||||
default:
|
||||
config_rpybuf[rs++] = '?';
|
||||
retval = REPLY_EPARAM;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'F':
|
||||
// Identify Current Firmware Function
|
||||
retval = REPLY_OK;
|
||||
#ifdef FUNCTION_VGA
|
||||
config_rpybuf[rs++] = 'V';
|
||||
config_rpybuf[rs++] = 'G';
|
||||
config_rpybuf[rs++] = 'A';
|
||||
#endif
|
||||
#ifdef FUNCTION_Z80
|
||||
config_rpybuf[rs++] = 'Z';
|
||||
config_rpybuf[rs++] = '8';
|
||||
config_rpybuf[rs++] = '0';
|
||||
#endif
|
||||
break;
|
||||
|
||||
case 'h':
|
||||
// Identify Hardware Type
|
||||
retval = REPLY_OK;
|
||||
config_rpybuf[rs++] = 0x02; // V2 Retro Computing
|
||||
#ifdef ANALOG_GS
|
||||
// AnalogGS Rev 1
|
||||
config_rpybuf[rs++] = 'G';
|
||||
config_rpybuf[rs++] = '1';
|
||||
#else
|
||||
// Analog Rev 1
|
||||
config_rpybuf[rs++] = 'A';
|
||||
config_rpybuf[rs++] = '1';
|
||||
#endif
|
||||
break;
|
||||
|
||||
case 'd':
|
||||
// Identify Date Request
|
||||
retval = REPLY_OK;
|
||||
config_rpybuf[rs++] = (BUILDDATE >> 24) & 0xFF;
|
||||
config_rpybuf[rs++] = (BUILDDATE >> 16) & 0xFF;
|
||||
config_rpybuf[rs++] = (BUILDDATE >> 8) & 0xFF;
|
||||
config_rpybuf[rs++] = (BUILDDATE >> 0) & 0xFF;
|
||||
config_rpybuf[rs++] = (BUILDID >> 8) & 0xFF;
|
||||
config_rpybuf[rs++] = (BUILDID >> 0) & 0xFF;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
// Unrecognized command
|
||||
retval = REPLY_ECMD;
|
||||
}
|
||||
|
||||
config_cmdbuf[7] = 0xFF;
|
||||
config_cmdbuf[6] = 0xFF;
|
||||
config_cmdbuf[5] = 0xFF;
|
||||
config_cmdbuf[4] = 0xFF;
|
||||
config_cmdbuf[3] = 0xFF;
|
||||
config_cmdbuf[2] = 0xFF;
|
||||
config_cmdbuf[1] = 0xFF;
|
||||
config_cmdbuf[0] = 0xFF;
|
||||
|
||||
config_rpybuf[0] = retval;
|
||||
}
|
111
common/config.h
Normal file
111
common/config.h
Normal file
@ -0,0 +1,111 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <pico/stdlib.h>
|
||||
#include "common/cfgtoken.h"
|
||||
|
||||
#ifndef CONFIG_SYSCLOCK
|
||||
#warning Defaulting to 126MHz
|
||||
#define CONFIG_SYSCLOCK 126.0 /* MHz */
|
||||
#endif
|
||||
|
||||
// Pin configuration
|
||||
#ifdef ANALOG_GS
|
||||
#define CONFIG_PIN_APPLEBUS_DATA_BASE 16 /* 8+2 pins */
|
||||
#define CONFIG_PIN_APPLEBUS_DEVSEL (CONFIG_PIN_APPLEBUS_DATA_BASE+8)
|
||||
#define CONFIG_PIN_APPLEBUS_RW (CONFIG_PIN_APPLEBUS_DATA_BASE+9)
|
||||
#define CONFIG_PIN_APPLEBUS_CONTROL_BASE 26 /* 4 pins */
|
||||
#define CONFIG_PIN_APPLEBUS_PHI0 14
|
||||
#else
|
||||
#define CONFIG_PIN_APPLEBUS_DATA_BASE 0 /* 8+2 pins */
|
||||
#define CONFIG_PIN_APPLEBUS_DEVSEL (CONFIG_PIN_APPLEBUS_DATA_BASE+8)
|
||||
#define CONFIG_PIN_APPLEBUS_RW (CONFIG_PIN_APPLEBUS_DATA_BASE+9)
|
||||
#define CONFIG_PIN_APPLEBUS_CONTROL_BASE 10 /* 4 pins */
|
||||
#define CONFIG_PIN_APPLEBUS_PHI0 26
|
||||
#endif
|
||||
|
||||
#define CONFIG_ABUS_PIO pio1
|
||||
|
||||
#ifdef FUNCTION_VGA
|
||||
#ifdef ANALOG_GS
|
||||
#define CONFIG_PIN_HSYNC 13
|
||||
#define CONFIG_PIN_VSYNC 12
|
||||
#define CONFIG_PIN_RGB_BASE 0 /* 12 pins */
|
||||
#else
|
||||
#define CONFIG_PIN_HSYNC 28
|
||||
#define CONFIG_PIN_VSYNC 27
|
||||
#define CONFIG_PIN_RGB_BASE 14 /* 9 pins */
|
||||
#endif
|
||||
|
||||
// Other resources
|
||||
#define CONFIG_VGA_PIO pio0
|
||||
#define CONFIG_VGA_SPINLOCK_ID 31
|
||||
|
||||
extern volatile uint32_t mono_palette;
|
||||
extern volatile uint8_t terminal_tbcolor;
|
||||
extern volatile uint8_t terminal_border;
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef FUNCTION_Z80
|
||||
typedef enum {
|
||||
SERIAL_LOOP = 0,
|
||||
SERIAL_USB,
|
||||
SERIAL_WIFI,
|
||||
SERIAL_PRINTER,
|
||||
} serialmux_t;
|
||||
|
||||
extern volatile serialmux_t serialmux;
|
||||
|
||||
typedef enum {
|
||||
USB_HOST_CDC,
|
||||
USB_GUEST_CDC,
|
||||
USB_GUEST_MIDI,
|
||||
} usbmux_t;
|
||||
|
||||
extern volatile usbmux_t usbmux;
|
||||
|
||||
typedef enum {
|
||||
WIFI_CLIENT = 0,
|
||||
WIFI_AP,
|
||||
} wifimode_t;
|
||||
|
||||
extern volatile wifimode_t wifimode;
|
||||
#endif
|
||||
|
||||
typedef enum {
|
||||
MACHINE_II = 0,
|
||||
MACHINE_IIE = 1,
|
||||
MACHINE_IIGS = 2,
|
||||
MACHINE_PRAVETZ = 6,
|
||||
MACHINE_AGAT7 = 7,
|
||||
MACHINE_BASIS = 8,
|
||||
MACHINE_AGAT9 = 9,
|
||||
MACHINE_INVALID = 0xfe,
|
||||
MACHINE_AUTO = 0xff
|
||||
} compat_t;
|
||||
|
||||
extern volatile compat_t cfg_machine;
|
||||
extern volatile compat_t current_machine;
|
||||
|
||||
|
||||
void default_config();
|
||||
int make_config(uint8_t rev);
|
||||
bool read_config();
|
||||
bool write_config(bool onetime);
|
||||
|
||||
void config_handler();
|
||||
|
||||
void dmacopy32(uint32_t *start, uint32_t *end, uint32_t *source);
|
||||
|
||||
#if 1
|
||||
#define DELAYED_COPY_CODE(n) __noinline __attribute__((section(".delayed_code."))) n
|
||||
#else
|
||||
#define DELAYED_COPY_CODE(n) __noinline __time_critical_func(n)
|
||||
#endif
|
||||
|
||||
#if 1
|
||||
#define DELAYED_COPY_DATA(n) __attribute__((section(".delayed_data."))) n
|
||||
#else
|
||||
#define DELAYED_COPY_DATA(n) n
|
||||
#endif
|
50
common/dmacopy.c
Normal file
50
common/dmacopy.c
Normal file
@ -0,0 +1,50 @@
|
||||
#include <string.h>
|
||||
#include <hardware/dma.h>
|
||||
|
||||
static int dmacopy_channel = -1;
|
||||
|
||||
// TODO: mutex this!
|
||||
void __noinline memcpy32(void *dst, void *src, uint32_t size) {
|
||||
dma_channel_config c;
|
||||
|
||||
// Nothing to do!
|
||||
if(!size) return;
|
||||
|
||||
// Cowardly avoid unaligned transfers, let memcpy() handle them.
|
||||
if((size & 0x3) || (((uint32_t)dst) & 0x3) || (((uint32_t)src) & 0x3)) {
|
||||
memcpy(dst, src, size);
|
||||
return;
|
||||
}
|
||||
|
||||
// 32 bit transfers. Both read and write address increment after each
|
||||
// transfer (each pointing to a location in src or dst respectively).
|
||||
// No DREQ is selected, so the DMA transfers as fast as it can.
|
||||
|
||||
// Get a free channel, panic() if there are none
|
||||
if(dmacopy_channel == -1)
|
||||
dmacopy_channel = dma_claim_unused_channel(true);
|
||||
|
||||
c = dma_channel_get_default_config(dmacopy_channel);
|
||||
channel_config_set_transfer_data_size(&c, DMA_SIZE_32);
|
||||
channel_config_set_read_increment(&c, true);
|
||||
channel_config_set_write_increment(&c, true);
|
||||
|
||||
dma_channel_configure(dmacopy_channel, &c, dst, src, (size >> 2), true);
|
||||
|
||||
dma_channel_wait_for_finish_blocking(dmacopy_channel);
|
||||
|
||||
dma_channel_abort(dmacopy_channel);
|
||||
|
||||
// Deinit the DMA channel
|
||||
c = dma_channel_get_default_config(dmacopy_channel);
|
||||
dma_channel_configure(dmacopy_channel, &c, NULL, NULL, 0, false);
|
||||
channel_config_set_read_increment(&c, false);
|
||||
channel_config_set_write_increment(&c, false);
|
||||
}
|
||||
|
||||
void __noinline dmacpy32(void *start, void *end, void *source) {
|
||||
uint32_t size = ((uint32_t)end) - ((uint32_t)start);
|
||||
|
||||
memcpy32(start, source, size);
|
||||
}
|
||||
|
4
common/dmacopy.h
Normal file
4
common/dmacopy.h
Normal file
@ -0,0 +1,4 @@
|
||||
#pragma once
|
||||
|
||||
void memcpy32(void *dst, void *src, uint32_t size);
|
||||
void dmacpy32(void *start, void *end, void *source);
|
24
common/flash.c
Normal file
24
common/flash.c
Normal file
@ -0,0 +1,24 @@
|
||||
#include <pico/stdlib.h>
|
||||
#include <pico/multicore.h>
|
||||
#include <hardware/watchdog.h>
|
||||
#include <hardware/resets.h>
|
||||
#include "config.h"
|
||||
|
||||
#ifdef RASPBERRYPI_PICO_W
|
||||
#include <pico/cyw43_arch.h>
|
||||
#endif
|
||||
|
||||
void __time_critical_func(flash_reboot)() __attribute__ ((noreturn));
|
||||
|
||||
// Reboot the Pico
|
||||
void __time_critical_func(flash_reboot)() {
|
||||
save_and_disable_interrupts();
|
||||
|
||||
multicore_reset_core1();
|
||||
|
||||
reset_block((1<<11) | (1<<10) | (1<<2));
|
||||
|
||||
watchdog_enable(2, 1);
|
||||
for(;;);
|
||||
}
|
||||
|
69
common/flash.h
Normal file
69
common/flash.h
Normal file
@ -0,0 +1,69 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <hardware/flash.h>
|
||||
|
||||
#ifdef HAVE_8MB_FLASH
|
||||
#define FLASH_SIZE (8*1024*1024)
|
||||
#else
|
||||
#define FLASH_SIZE (2*1024*1024)
|
||||
#endif
|
||||
#define FLASH_TOP (XIP_BASE + FLASH_SIZE)
|
||||
#define FLASH_RESERVED (FLASH_TOP - (256*1024))
|
||||
|
||||
#define CONFIG_SIZE (4*1024)
|
||||
#define FLASH_CONFIG_ONETIME (FLASH_RESERVED - CONFIG_SIZE)
|
||||
#define FLASH_CONFIG_PRIMARY (FLASH_CONFIG_ONETIME - CONFIG_SIZE)
|
||||
#define FLASH_CONFIG_SECONDARY (FLASH_CONFIG_PRIMARY - CONFIG_SIZE)
|
||||
|
||||
#define FONT_SIZE (4*1024)
|
||||
#define FONT_COUNT 40
|
||||
#define FLASH_FONT_BASE (FLASH_CONFIG_SECONDARY - (FONT_SIZE * FONT_COUNT))
|
||||
#define FLASH_FONT(n) (FLASH_FONT_BASE + (FONT_SIZE * (n)))
|
||||
|
||||
#define FLASH_FONT_ROMXE00 FLASH_FONT(0x00)
|
||||
#define FLASH_FONT_ROMXE01 FLASH_FONT(0x01)
|
||||
#define FLASH_FONT_ROMXE02 FLASH_FONT(0x02)
|
||||
#define FLASH_FONT_ROMXE03 FLASH_FONT(0x03)
|
||||
#define FLASH_FONT_ROMXE04 FLASH_FONT(0x04)
|
||||
#define FLASH_FONT_ROMXE05 FLASH_FONT(0x05)
|
||||
#define FLASH_FONT_ROMXE06 FLASH_FONT(0x06)
|
||||
#define FLASH_FONT_ROMXE07 FLASH_FONT(0x07)
|
||||
#define FLASH_FONT_ROMXE08 FLASH_FONT(0x08)
|
||||
#define FLASH_FONT_ROMXE09 FLASH_FONT(0x09)
|
||||
#define FLASH_FONT_ROMXE0A FLASH_FONT(0x0A)
|
||||
#define FLASH_FONT_ROMXE0B FLASH_FONT(0x0B)
|
||||
#define FLASH_FONT_ROMXE0C FLASH_FONT(0x0C)
|
||||
#define FLASH_FONT_ROMXE0D FLASH_FONT(0x0D)
|
||||
#define FLASH_FONT_ROMXE0E FLASH_FONT(0x0E)
|
||||
#define FLASH_FONT_ROMXE0F FLASH_FONT(0x0F)
|
||||
#define FLASH_FONT_ROMXE10 FLASH_FONT(0x10)
|
||||
#define FLASH_FONT_ROMXE11 FLASH_FONT(0x11)
|
||||
#define FLASH_FONT_ROMXE12 FLASH_FONT(0x12)
|
||||
#define FLASH_FONT_ROMXE13 FLASH_FONT(0x13)
|
||||
#define FLASH_FONT_ROMXE14 FLASH_FONT(0x14)
|
||||
#define FLASH_FONT_ROMXE15 FLASH_FONT(0x15)
|
||||
#define FLASH_FONT_ROMXE16 FLASH_FONT(0x16)
|
||||
#define FLASH_FONT_ROMXE17 FLASH_FONT(0x17)
|
||||
#define FLASH_FONT_ROMXE18 FLASH_FONT(0x18)
|
||||
#define FLASH_FONT_ROMXE19 FLASH_FONT(0x19)
|
||||
#define FLASH_FONT_ROMXE1A FLASH_FONT(0x1A)
|
||||
#define FLASH_FONT_ROMXE1B FLASH_FONT(0x1B)
|
||||
#define FLASH_FONT_ROMXE1C FLASH_FONT(0x1C)
|
||||
#define FLASH_FONT_ROMXE1D FLASH_FONT(0x1D)
|
||||
#define FLASH_FONT_ROMXE1E FLASH_FONT(0x1E)
|
||||
#define FLASH_FONT_ROMXE1F FLASH_FONT(0x1F)
|
||||
#define FLASH_FONT_APPLE_II FLASH_FONT(0x20)
|
||||
#define FLASH_FONT_APPLE_IIE FLASH_FONT(0x21)
|
||||
#define FLASH_FONT_APPLE_IIGS FLASH_FONT(0x22)
|
||||
#define FLASH_FONT_PRAVETZ FLASH_FONT(0x23)
|
||||
#define FLASH_FONT_EXTRA24 FLASH_FONT(0x24)
|
||||
#define FLASH_FONT_EXTRA25 FLASH_FONT(0x25)
|
||||
#define FLASH_FONT_EXTRA26 FLASH_FONT(0x26)
|
||||
#define FLASH_FONT_EXTRA27 FLASH_FONT(0x27)
|
||||
|
||||
// Firmware for $C000-$CFFF
|
||||
#define FLASH_6502_SIZE (4*1024)
|
||||
#define FLASH_6502_BASE (FLASH_FONT_BASE - FLASH_6502_SIZE)
|
||||
|
||||
extern void flash_reboot() __attribute__ ((noreturn));
|
177
common/main.c
Normal file
177
common/main.c
Normal file
@ -0,0 +1,177 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <pico/stdlib.h>
|
||||
#include <pico/multicore.h>
|
||||
#include <hardware/pio.h>
|
||||
#include "common/abus.h"
|
||||
#include "common/config.h"
|
||||
#include "common/modes.h"
|
||||
#include "common/buffers.h"
|
||||
#include "common/flash.h"
|
||||
#include "common/dmacopy.h"
|
||||
|
||||
#ifdef RASPBERRYPI_PICO_W
|
||||
#include <pico/cyw43_arch.h>
|
||||
#endif
|
||||
|
||||
#define ACCESS_READ ((value & (1u << CONFIG_PIN_APPLEBUS_RW-CONFIG_PIN_APPLEBUS_DATA_BASE)) != 0)
|
||||
#define ACCESS_WRITE ((value & (1u << CONFIG_PIN_APPLEBUS_RW-CONFIG_PIN_APPLEBUS_DATA_BASE)) == 0)
|
||||
|
||||
static void __noinline __time_critical_func(core1_loop)() {
|
||||
uint32_t value;
|
||||
uint32_t address;
|
||||
|
||||
for(;;) {
|
||||
value = pio_sm_get_blocking(CONFIG_ABUS_PIO, ABUS_MAIN_SM);
|
||||
address = (value >> 10) & 0xffff;
|
||||
|
||||
// device read access
|
||||
if(ACCESS_READ) {
|
||||
if(CARD_SELECT) {
|
||||
//pio_sm_put(CONFIG_ABUS_PIO, ABUS_DEVICE_READ_SM, apple_memory[address]);
|
||||
CONFIG_ABUS_PIO->txf[ABUS_DEVICE_READ_SM] = apple_memory[address];
|
||||
}
|
||||
}
|
||||
|
||||
busactive = 1;
|
||||
|
||||
if(CARD_SELECT) {
|
||||
if(CARD_DEVSEL) {
|
||||
cardslot = (address >> 4) & 0x7;
|
||||
} else if(CARD_IOSEL) {
|
||||
cardslot = (address >> 8) & 0x7;
|
||||
|
||||
// Config memory in card slot-rom address space
|
||||
if(ACCESS_WRITE) {
|
||||
if((address & 0xFF) == 0xED) {
|
||||
apple_memory[address] = value;
|
||||
cfptr = (cfptr & 0x1F00) | value;
|
||||
apple_memory[address] = cfbuf[cfptr];
|
||||
}
|
||||
if((address & 0xFF) == 0xEE) {
|
||||
apple_memory[address] = value & 0x1F;
|
||||
cfptr = ((cfptr & 0xFF) | (value << 8)) & 0x1FFF;
|
||||
apple_memory[address] = cfbuf[cfptr];
|
||||
}
|
||||
if((address & 0xFF) == 0xEF) {
|
||||
apple_memory[address] = value;
|
||||
cfbuf[cfptr] = value;
|
||||
}
|
||||
if((address & 0xFF) >= 0xF0) {
|
||||
apple_memory[address] = value;
|
||||
}
|
||||
}
|
||||
if((address & 0xFF) == 0xEF) {
|
||||
cfptr = (cfptr + 1) & 0x1FFF;
|
||||
apple_memory[address] = cfbuf[cfptr];
|
||||
apple_memory[address-1] = (cfptr >> 8) & 0xff;
|
||||
apple_memory[address-2] = cfptr & 0xff;
|
||||
}
|
||||
|
||||
// Stop further processing by businterface
|
||||
continue;
|
||||
}
|
||||
#ifdef FUNCTION_VGA
|
||||
} else if(current_machine == MACHINE_AUTO) {
|
||||
if((apple_memory[0x0417] == 0xE7) && (apple_memory[0x416] == 0xC9)) { // Apple IIgs
|
||||
current_machine = MACHINE_IIGS;
|
||||
internal_flags &= ~IFLAGS_IIE_REGS;
|
||||
internal_flags |= IFLAGS_IIGS_REGS;
|
||||
} else if((apple_memory[0x0417] == 0xE5) && (apple_memory[0x416] == 0xAF)) { // Apple //e Enhanced
|
||||
current_machine = MACHINE_IIE;
|
||||
internal_flags |= IFLAGS_IIE_REGS;
|
||||
internal_flags &= ~IFLAGS_IIGS_REGS;
|
||||
} else if((apple_memory[0x0415] == 0xDD) && (apple_memory[0x413] == 0xE5)) { // Apple //e Unenhanced
|
||||
current_machine = MACHINE_IIE;
|
||||
internal_flags |= IFLAGS_IIE_REGS;
|
||||
internal_flags &= ~IFLAGS_IIGS_REGS;
|
||||
} else if(apple_memory[0x0410] == 0xD0) { // Apple II/Plus/J-Plus with Autostart
|
||||
current_machine = MACHINE_II;
|
||||
internal_flags &= ~(IFLAGS_IIE_REGS | IFLAGS_IIGS_REGS);
|
||||
} else if((apple_memory[0x07D0] == 0xAA) && (apple_memory[0x07D1] == 0x60)) { // Apple II without Autostart
|
||||
current_machine = MACHINE_II;
|
||||
internal_flags &= ~(IFLAGS_IIE_REGS | IFLAGS_IIGS_REGS);
|
||||
} else if(apple_memory[0x0410] == 0xF2) { // Pravetz!
|
||||
current_machine = MACHINE_PRAVETZ;
|
||||
internal_flags &= ~(IFLAGS_IIE_REGS | IFLAGS_IIGS_REGS);
|
||||
}
|
||||
#endif
|
||||
} else switch(reset_state) {
|
||||
case 0:
|
||||
if((value & 0x3FFFF00) == ((0xFFFC << 10) | 0x300))
|
||||
reset_state++;
|
||||
break;
|
||||
case 1:
|
||||
if((value & 0x3FFFF00) == ((0xFFFD << 10) | 0x300))
|
||||
reset_state++;
|
||||
else
|
||||
reset_state=0;
|
||||
break;
|
||||
case 2:
|
||||
if((value & 0x3FFFF00) == ((0xFA62 << 10) | 0x300))
|
||||
reset_state++;
|
||||
else
|
||||
reset_state=0;
|
||||
break;
|
||||
case 3:
|
||||
#ifdef FUNCTION_VGA
|
||||
soft_switches = SOFTSW_TEXT_MODE;
|
||||
soft_switches &= ~SOFTSW_80COL;
|
||||
#endif
|
||||
default:
|
||||
reset_state = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
#ifdef FUNCTION_VGA
|
||||
vga_businterface(address, value);
|
||||
#endif
|
||||
#ifdef FUNCTION_Z80
|
||||
z80_businterface(address, value);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
static void DELAYED_COPY_CODE(core0_loop)() {
|
||||
#ifdef FUNCTION_VGA
|
||||
for(;;) vgamain();
|
||||
#endif
|
||||
#ifdef FUNCTION_Z80
|
||||
for(;;) z80main();
|
||||
#endif
|
||||
}
|
||||
|
||||
extern uint32_t __ram_delayed_copy_source__[];
|
||||
extern uint32_t __ram_delayed_copy_start__[];
|
||||
extern uint32_t __ram_delayed_copy_end__[];
|
||||
|
||||
int main() {
|
||||
// Adjust system clock for better dividing into other clocks
|
||||
set_sys_clock_khz(CONFIG_SYSCLOCK*1000, true);
|
||||
|
||||
abus_init();
|
||||
|
||||
multicore_launch_core1(core1_loop);
|
||||
|
||||
// Load 6502 code from flash into the memory buffer
|
||||
memcpy32((void*)apple_memory+0xC000, (void *)FLASH_6502_BASE, FLASH_6502_SIZE);
|
||||
|
||||
// Initialize the config window in each rom slot
|
||||
memcpy((uint8_t*)apple_memory+0xC1F0, "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFFV2ANALOG", 16);
|
||||
memcpy((uint8_t*)apple_memory+0xC2F0, "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFFV2ANALOG", 16);
|
||||
memcpy((uint8_t*)apple_memory+0xC3F0, "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFFV2ANALOG", 16);
|
||||
memcpy((uint8_t*)apple_memory+0xC4F0, "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFFV2ANALOG", 16);
|
||||
memcpy((uint8_t*)apple_memory+0xC5F0, "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFFV2ANALOG", 16);
|
||||
memcpy((uint8_t*)apple_memory+0xC6F0, "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFFV2ANALOG", 16);
|
||||
memcpy((uint8_t*)apple_memory+0xC7F0, "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFFV2ANALOG", 16);
|
||||
|
||||
// Finish copying remaining data and code to RAM from flash
|
||||
dmacpy32(__ram_delayed_copy_start__, __ram_delayed_copy_end__, __ram_delayed_copy_source__);
|
||||
|
||||
// Sensible defaults if there is no config / fs
|
||||
default_config();
|
||||
|
||||
core0_loop();
|
||||
|
||||
return 0;
|
||||
}
|
18
common/modes.h
Normal file
18
common/modes.h
Normal file
@ -0,0 +1,18 @@
|
||||
|
||||
void vgamain();
|
||||
void vga_businterface(uint32_t address, uint32_t value);
|
||||
|
||||
void z80main();
|
||||
void z80_businterface(uint32_t address, uint32_t value);
|
||||
|
||||
void serialmain();
|
||||
void serial_businterface(uint32_t address, uint32_t value);
|
||||
|
||||
void parallelmain();
|
||||
void parallel_businterface(uint32_t address, uint32_t value);
|
||||
|
||||
void diagmain();
|
||||
void diag_businterface(uint32_t address, uint32_t value);
|
||||
|
||||
void fsmain();
|
||||
void fs_businterface(uint32_t address, uint32_t value);
|
238
common/usb_descriptors.c
Normal file
238
common/usb_descriptors.c
Normal file
@ -0,0 +1,238 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2019 Ha Thach (tinyusb.org)
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "tusb.h"
|
||||
|
||||
|
||||
/* A combination of interfaces must have a unique product id, since PC will save device driver after the first plug.
|
||||
* Same VID/PID with different interface e.g MSC (first), then CDC (later) will possibly cause system error on PC.
|
||||
*
|
||||
* Auto ProductID layout's Bitmap:
|
||||
* [MSB] MIDI | HID | MSC | CDC [LSB]
|
||||
*/
|
||||
#define _PID_MAP(itf, n) ( (CFG_TUD_##itf) << (n) )
|
||||
#define USB_PID (0x4000 | _PID_MAP(CDC, 0) | _PID_MAP(MSC, 1) | _PID_MAP(HID, 2) | \
|
||||
_PID_MAP(MIDI, 3) | _PID_MAP(VENDOR, 4) )
|
||||
|
||||
#define USB_VID 0xCafe
|
||||
#define USB_BCD 0x0200
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// Device Descriptors
|
||||
//--------------------------------------------------------------------+
|
||||
tusb_desc_device_t const desc_device =
|
||||
{
|
||||
.bLength = sizeof(tusb_desc_device_t),
|
||||
.bDescriptorType = TUSB_DESC_DEVICE,
|
||||
.bcdUSB = USB_BCD,
|
||||
|
||||
// Use Interface Association Descriptor (IAD) for CDC
|
||||
// As required by USB Specs IAD's subclass must be common class (2) and protocol must be IAD (1)
|
||||
.bDeviceClass = TUSB_CLASS_MISC,
|
||||
.bDeviceSubClass = MISC_SUBCLASS_COMMON,
|
||||
.bDeviceProtocol = MISC_PROTOCOL_IAD,
|
||||
.bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE,
|
||||
|
||||
.idVendor = USB_VID,
|
||||
.idProduct = USB_PID,
|
||||
.bcdDevice = 0x0100,
|
||||
|
||||
.iManufacturer = 0x01,
|
||||
.iProduct = 0x02,
|
||||
.iSerialNumber = 0x03,
|
||||
|
||||
.bNumConfigurations = 0x01
|
||||
};
|
||||
|
||||
// Invoked when received GET DEVICE DESCRIPTOR
|
||||
// Application return pointer to descriptor
|
||||
uint8_t const * tud_descriptor_device_cb(void)
|
||||
{
|
||||
return (uint8_t const *) &desc_device;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// Configuration Descriptor
|
||||
//--------------------------------------------------------------------+
|
||||
enum
|
||||
{
|
||||
ITF_NUM_CDC_0 = 0,
|
||||
ITF_NUM_CDC_0_DATA,
|
||||
ITF_NUM_TOTAL
|
||||
};
|
||||
|
||||
#define CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + CFG_TUD_CDC * TUD_CDC_DESC_LEN)
|
||||
|
||||
#if CFG_TUSB_MCU == OPT_MCU_LPC175X_6X || CFG_TUSB_MCU == OPT_MCU_LPC177X_8X || CFG_TUSB_MCU == OPT_MCU_LPC40XX
|
||||
// LPC 17xx and 40xx endpoint type (bulk/interrupt/iso) are fixed by its number
|
||||
// 0 control, 1 In, 2 Bulk, 3 Iso, 4 In etc ...
|
||||
#define EPNUM_CDC_0_NOTIF 0x81
|
||||
#define EPNUM_CDC_0_OUT 0x02
|
||||
#define EPNUM_CDC_0_IN 0x82
|
||||
|
||||
#elif CFG_TUSB_MCU == OPT_MCU_SAMG || CFG_TUSB_MCU == OPT_MCU_SAMX7X
|
||||
// SAMG & SAME70 don't support a same endpoint number with different direction IN and OUT
|
||||
// e.g EP1 OUT & EP1 IN cannot exist together
|
||||
#define EPNUM_CDC_0_NOTIF 0x81
|
||||
#define EPNUM_CDC_0_OUT 0x02
|
||||
#define EPNUM_CDC_0_IN 0x83
|
||||
|
||||
#else
|
||||
#define EPNUM_CDC_0_NOTIF 0x81
|
||||
#define EPNUM_CDC_0_OUT 0x02
|
||||
#define EPNUM_CDC_0_IN 0x82
|
||||
|
||||
#endif
|
||||
|
||||
uint8_t const desc_fs_configuration[] =
|
||||
{
|
||||
// Config number, interface count, string index, total length, attribute, power in mA
|
||||
TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, 0x00, 100),
|
||||
|
||||
// 1st CDC: Interface number, string index, EP notification address and size, EP data address (out, in) and size.
|
||||
TUD_CDC_DESCRIPTOR(ITF_NUM_CDC_0, 4, EPNUM_CDC_0_NOTIF, 8, EPNUM_CDC_0_OUT, EPNUM_CDC_0_IN, 64),
|
||||
|
||||
// 2nd CDC: Interface number, string index, EP notification address and size, EP data address (out, in) and size.
|
||||
//TUD_CDC_DESCRIPTOR(ITF_NUM_CDC_1, 4, EPNUM_CDC_1_NOTIF, 8, EPNUM_CDC_1_OUT, EPNUM_CDC_1_IN, 64),
|
||||
};
|
||||
|
||||
#if TUD_OPT_HIGH_SPEED
|
||||
// Per USB specs: high speed capable device must report device_qualifier and other_speed_configuration
|
||||
|
||||
uint8_t const desc_hs_configuration[] =
|
||||
{
|
||||
// Config number, interface count, string index, total length, attribute, power in mA
|
||||
TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, 0x00, 100),
|
||||
|
||||
// 1st CDC: Interface number, string index, EP notification address and size, EP data address (out, in) and size.
|
||||
TUD_CDC_DESCRIPTOR(ITF_NUM_CDC_0, 4, EPNUM_CDC_0_NOTIF, 8, EPNUM_CDC_0_OUT, EPNUM_CDC_0_IN, 512),
|
||||
};
|
||||
|
||||
// device qualifier is mostly similar to device descriptor since we don't change configuration based on speed
|
||||
tusb_desc_device_qualifier_t const desc_device_qualifier =
|
||||
{
|
||||
.bLength = sizeof(tusb_desc_device_t),
|
||||
.bDescriptorType = TUSB_DESC_DEVICE,
|
||||
.bcdUSB = USB_BCD,
|
||||
|
||||
.bDeviceClass = TUSB_CLASS_MISC,
|
||||
.bDeviceSubClass = MISC_SUBCLASS_COMMON,
|
||||
.bDeviceProtocol = MISC_PROTOCOL_IAD,
|
||||
|
||||
.bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE,
|
||||
.bNumConfigurations = 0x01,
|
||||
.bReserved = 0x00
|
||||
};
|
||||
|
||||
// Invoked when received GET DEVICE QUALIFIER DESCRIPTOR request
|
||||
// Application return pointer to descriptor, whose contents must exist long enough for transfer to complete.
|
||||
// device_qualifier descriptor describes information about a high-speed capable device that would
|
||||
// change if the device were operating at the other speed. If not highspeed capable stall this request.
|
||||
uint8_t const* tud_descriptor_device_qualifier_cb(void)
|
||||
{
|
||||
return (uint8_t const*) &desc_device_qualifier;
|
||||
}
|
||||
|
||||
// Invoked when received GET OTHER SEED CONFIGURATION DESCRIPTOR request
|
||||
// Application return pointer to descriptor, whose contents must exist long enough for transfer to complete
|
||||
// Configuration descriptor in the other speed e.g if high speed then this is for full speed and vice versa
|
||||
uint8_t const* tud_descriptor_other_speed_configuration_cb(uint8_t index)
|
||||
{
|
||||
(void) index; // for multiple configurations
|
||||
|
||||
// if link speed is high return fullspeed config, and vice versa
|
||||
return (tud_speed_get() == TUSB_SPEED_HIGH) ? desc_fs_configuration : desc_hs_configuration;
|
||||
}
|
||||
|
||||
#endif // highspeed
|
||||
|
||||
// Invoked when received GET CONFIGURATION DESCRIPTOR
|
||||
// Application return pointer to descriptor
|
||||
// Descriptor contents must exist long enough for transfer to complete
|
||||
uint8_t const * tud_descriptor_configuration_cb(uint8_t index)
|
||||
{
|
||||
(void) index; // for multiple configurations
|
||||
|
||||
#if TUD_OPT_HIGH_SPEED
|
||||
// Although we are highspeed, host may be fullspeed.
|
||||
return (tud_speed_get() == TUSB_SPEED_HIGH) ? desc_hs_configuration : desc_fs_configuration;
|
||||
#else
|
||||
return desc_fs_configuration;
|
||||
#endif
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// String Descriptors
|
||||
//--------------------------------------------------------------------+
|
||||
|
||||
// array of pointer to string descriptors
|
||||
char const* string_desc_arr [] =
|
||||
{
|
||||
(const char[]) { 0x09, 0x04 }, // 0: is supported language is English (0x0409)
|
||||
"V2Retro", // 1: Manufacturer
|
||||
"V2 Analog VGA", // 2: Product
|
||||
"123456", // 3: Serials, should use chip ID
|
||||
"V2 Analog CDC", // 4: CDC Interface
|
||||
};
|
||||
|
||||
static uint16_t _desc_str[32];
|
||||
|
||||
// Invoked when received GET STRING DESCRIPTOR request
|
||||
// Application return pointer to descriptor, whose contents must exist long enough for transfer to complete
|
||||
uint16_t const* tud_descriptor_string_cb(uint8_t index, uint16_t langid)
|
||||
{
|
||||
(void) langid;
|
||||
|
||||
uint8_t chr_count;
|
||||
|
||||
if ( index == 0)
|
||||
{
|
||||
memcpy(&_desc_str[1], string_desc_arr[0], 2);
|
||||
chr_count = 1;
|
||||
}else
|
||||
{
|
||||
// Note: the 0xEE index string is a Microsoft OS 1.0 Descriptors.
|
||||
// https://docs.microsoft.com/en-us/windows-hardware/drivers/usbcon/microsoft-defined-usb-descriptors
|
||||
|
||||
if ( !(index < sizeof(string_desc_arr)/sizeof(string_desc_arr[0])) ) return NULL;
|
||||
|
||||
const char* str = string_desc_arr[index];
|
||||
|
||||
// Cap at max char
|
||||
chr_count = strlen(str);
|
||||
if ( chr_count > 31 ) chr_count = 31;
|
||||
|
||||
// Convert ASCII string into UTF-16
|
||||
for(uint8_t i=0; i<chr_count; i++)
|
||||
{
|
||||
_desc_str[1+i] = str[i];
|
||||
}
|
||||
}
|
||||
|
||||
// first byte is length (including header), second byte is string type
|
||||
_desc_str[0] = (TUSB_DESC_STRING << 8 ) | (2*chr_count + 2);
|
||||
|
||||
return _desc_str;
|
||||
}
|
271
delayed_copy.ld
Normal file
271
delayed_copy.ld
Normal file
@ -0,0 +1,271 @@
|
||||
/* Based on GCC ARM embedded samples.
|
||||
Defines the following symbols for use by code:
|
||||
__exidx_start
|
||||
__exidx_end
|
||||
__etext
|
||||
__data_start__
|
||||
__preinit_array_start
|
||||
__preinit_array_end
|
||||
__init_array_start
|
||||
__init_array_end
|
||||
__fini_array_start
|
||||
__fini_array_end
|
||||
__data_end__
|
||||
__bss_start__
|
||||
__bss_end__
|
||||
__end__
|
||||
end
|
||||
__HeapLimit
|
||||
__StackLimit
|
||||
__StackTop
|
||||
__stack (== StackTop)
|
||||
*/
|
||||
|
||||
MEMORY
|
||||
{
|
||||
FLASH(rx) : ORIGIN = 0x10000000, LENGTH = 2048k
|
||||
RAM(rwx) : ORIGIN = 0x20000000, LENGTH = 128k
|
||||
APPLEDATA(rwx) : ORIGIN = 0x20020000, LENGTH = 128k
|
||||
SCRATCH_X(rwx) : ORIGIN = 0x20040000, LENGTH = 4k
|
||||
SCRATCH_Y(rwx) : ORIGIN = 0x20041000, LENGTH = 4k
|
||||
}
|
||||
|
||||
ENTRY(_entry_point)
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
/* Second stage bootloader is prepended to the image. It must be 256 bytes big
|
||||
and checksummed. It is usually built by the boot_stage2 target
|
||||
in the Raspberry Pi Pico SDK
|
||||
*/
|
||||
|
||||
.flash_begin : {
|
||||
__flash_binary_start = .;
|
||||
} > FLASH
|
||||
|
||||
.boot2 : {
|
||||
__boot2_start__ = .;
|
||||
KEEP (*(.boot2))
|
||||
__boot2_end__ = .;
|
||||
} > FLASH
|
||||
|
||||
ASSERT(__boot2_end__ - __boot2_start__ == 256,
|
||||
"ERROR: Pico second stage bootloader must be 256 bytes in size")
|
||||
|
||||
/* The second stage will always enter the image at the start of .text.
|
||||
The debugger will use the ELF entry point, which is the _entry_point
|
||||
symbol if present, otherwise defaults to start of .text.
|
||||
This can be used to transfer control back to the bootrom on debugger
|
||||
launches only, to perform proper flash setup.
|
||||
*/
|
||||
|
||||
.text : {
|
||||
__logical_binary_start = .;
|
||||
KEEP (*(.vectors))
|
||||
KEEP (*(.binary_info_header))
|
||||
__binary_info_header_end = .;
|
||||
KEEP (*(.reset))
|
||||
/* TODO revisit this now memset/memcpy/float in ROM */
|
||||
/* bit of a hack right now to exclude all floating point and time critical (e.g. memset, memcpy) code from
|
||||
* FLASH ... we will include any thing excluded here in .data below by default */
|
||||
*(.init)
|
||||
*(EXCLUDE_FILE(*libgcc.a: *libc.a:*lib_a-mem*.o *libm.a:) .text*)
|
||||
*(.fini)
|
||||
/* Pull all c'tors into .text */
|
||||
*crtbegin.o(.ctors)
|
||||
*crtbegin?.o(.ctors)
|
||||
*(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors)
|
||||
*(SORT(.ctors.*))
|
||||
*(.ctors)
|
||||
/* Followed by destructors */
|
||||
*crtbegin.o(.dtors)
|
||||
*crtbegin?.o(.dtors)
|
||||
*(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors)
|
||||
*(SORT(.dtors.*))
|
||||
*(.dtors)
|
||||
|
||||
*(.eh_frame*)
|
||||
. = ALIGN(4);
|
||||
} > FLASH
|
||||
|
||||
.rodata : {
|
||||
*(EXCLUDE_FILE(*libgcc.a: *libc.a:*lib_a-mem*.o *libm.a:) .rodata*)
|
||||
. = ALIGN(4);
|
||||
*(SORT_BY_ALIGNMENT(SORT_BY_NAME(.flashdata*)))
|
||||
. = ALIGN(4);
|
||||
} > FLASH
|
||||
|
||||
.ARM.extab :
|
||||
{
|
||||
*(.ARM.extab* .gnu.linkonce.armextab.*)
|
||||
} > FLASH
|
||||
|
||||
__exidx_start = .;
|
||||
.ARM.exidx :
|
||||
{
|
||||
*(.ARM.exidx* .gnu.linkonce.armexidx.*)
|
||||
} > FLASH
|
||||
__exidx_end = .;
|
||||
|
||||
/* Machine inspectable binary information */
|
||||
. = ALIGN(4);
|
||||
__binary_info_start = .;
|
||||
.binary_info :
|
||||
{
|
||||
KEEP(*(.binary_info.keep.*))
|
||||
*(.binary_info.*)
|
||||
} > FLASH
|
||||
__binary_info_end = .;
|
||||
. = ALIGN(4);
|
||||
|
||||
/* End of .text-like segments */
|
||||
__etext = .;
|
||||
|
||||
.ram_vector_table (COPY): {
|
||||
*(.ram_vector_table)
|
||||
} > RAM
|
||||
|
||||
.data : {
|
||||
__data_start__ = .;
|
||||
*(vtable)
|
||||
|
||||
*(.time_critical*)
|
||||
|
||||
/* remaining .text and .rodata; i.e. stuff we exclude above because we want it in RAM */
|
||||
*(.text*)
|
||||
. = ALIGN(4);
|
||||
*(.rodata*)
|
||||
. = ALIGN(4);
|
||||
|
||||
*(.data*)
|
||||
|
||||
. = ALIGN(4);
|
||||
*(.after_data.*)
|
||||
. = ALIGN(4);
|
||||
/* preinit data */
|
||||
PROVIDE_HIDDEN (__mutex_array_start = .);
|
||||
KEEP(*(SORT(.mutex_array.*)))
|
||||
KEEP(*(.mutex_array))
|
||||
PROVIDE_HIDDEN (__mutex_array_end = .);
|
||||
|
||||
. = ALIGN(4);
|
||||
/* preinit data */
|
||||
PROVIDE_HIDDEN (__preinit_array_start = .);
|
||||
KEEP(*(SORT(.preinit_array.*)))
|
||||
KEEP(*(.preinit_array))
|
||||
PROVIDE_HIDDEN (__preinit_array_end = .);
|
||||
|
||||
. = ALIGN(4);
|
||||
/* init data */
|
||||
PROVIDE_HIDDEN (__init_array_start = .);
|
||||
KEEP(*(SORT(.init_array.*)))
|
||||
KEEP(*(.init_array))
|
||||
PROVIDE_HIDDEN (__init_array_end = .);
|
||||
|
||||
. = ALIGN(4);
|
||||
/* finit data */
|
||||
PROVIDE_HIDDEN (__fini_array_start = .);
|
||||
*(SORT(.fini_array.*))
|
||||
*(.fini_array)
|
||||
PROVIDE_HIDDEN (__fini_array_end = .);
|
||||
|
||||
*(.jcr)
|
||||
. = ALIGN(4);
|
||||
/* All data end */
|
||||
__data_end__ = .;
|
||||
} > RAM AT> FLASH
|
||||
|
||||
.delayed_copy : {
|
||||
__ram_delayed_copy_start__ = .;
|
||||
*(.delayed_code.*)
|
||||
. = ALIGN(4);
|
||||
|
||||
*(.delayed_data.*)
|
||||
. = ALIGN(4);
|
||||
__ram_delayed_copy_end__ = .;
|
||||
} > RAM AT> FLASH
|
||||
__ram_delayed_copy_source__ = LOADADDR(.delayed_copy);
|
||||
|
||||
.uninitialized_data (COPY): {
|
||||
. = ALIGN(4);
|
||||
*(.uninitialized_data*)
|
||||
} > RAM
|
||||
|
||||
.appledata (COPY): {
|
||||
__appledata_start__ = .;
|
||||
*(.appledata.*)
|
||||
. = ALIGN(4);
|
||||
__appledata_end__ = .;
|
||||
} > APPLEDATA
|
||||
|
||||
/* Start and end symbols must be word-aligned */
|
||||
.scratch_x : {
|
||||
__scratch_x_start__ = .;
|
||||
*(.scratch_x.*)
|
||||
. = ALIGN(4);
|
||||
__scratch_x_end__ = .;
|
||||
} > SCRATCH_X AT > FLASH
|
||||
__scratch_x_source__ = LOADADDR(.scratch_x);
|
||||
|
||||
.scratch_y : {
|
||||
__scratch_y_start__ = .;
|
||||
*(.scratch_y.*)
|
||||
. = ALIGN(4);
|
||||
__scratch_y_end__ = .;
|
||||
} > SCRATCH_Y AT > FLASH
|
||||
__scratch_y_source__ = LOADADDR(.scratch_y);
|
||||
|
||||
.bss : {
|
||||
. = ALIGN(4);
|
||||
__bss_start__ = .;
|
||||
*(SORT_BY_ALIGNMENT(SORT_BY_NAME(.bss*)))
|
||||
*(COMMON)
|
||||
. = ALIGN(4);
|
||||
__bss_end__ = .;
|
||||
} > RAM
|
||||
|
||||
.heap (COPY):
|
||||
{
|
||||
__end__ = .;
|
||||
end = __end__;
|
||||
*(.heap*)
|
||||
__HeapLimit = .;
|
||||
} > RAM
|
||||
|
||||
/* .stack*_dummy section doesn't contains any symbols. It is only
|
||||
* used for linker to calculate size of stack sections, and assign
|
||||
* values to stack symbols later
|
||||
*
|
||||
* stack1 section may be empty/missing if platform_launch_core1 is not used */
|
||||
|
||||
/* by default we put core 0 stack at the end of scratch Y, so that if core 1
|
||||
* stack is not used then all of SCRATCH_X is free.
|
||||
*/
|
||||
.stack1_dummy (COPY):
|
||||
{
|
||||
*(.stack1*)
|
||||
} > SCRATCH_X
|
||||
.stack_dummy (COPY):
|
||||
{
|
||||
*(.stack*)
|
||||
} > SCRATCH_Y
|
||||
|
||||
.flash_end : {
|
||||
__flash_binary_end = .;
|
||||
} > FLASH
|
||||
|
||||
/* stack limit is poorly named, but historically is maximum heap ptr */
|
||||
__StackLimit = ORIGIN(RAM) + LENGTH(RAM);
|
||||
__StackOneTop = ORIGIN(SCRATCH_X) + LENGTH(SCRATCH_X);
|
||||
__StackTop = ORIGIN(SCRATCH_Y) + LENGTH(SCRATCH_Y);
|
||||
__StackOneBottom = __StackOneTop - SIZEOF(.stack1_dummy);
|
||||
__StackBottom = __StackTop - SIZEOF(.stack_dummy);
|
||||
PROVIDE(__stack = __StackTop);
|
||||
|
||||
/* Check if data + heap + stack exceeds RAM limit */
|
||||
ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed")
|
||||
|
||||
ASSERT( __binary_info_header_end - __logical_binary_start <= 256, "Binary info must be in first 256 bytes of the binary")
|
||||
/* todo assert on extra code */
|
||||
}
|
||||
|
91
lwipopts.h
Normal file
91
lwipopts.h
Normal file
@ -0,0 +1,91 @@
|
||||
#ifndef _LWIPOPTS_H
|
||||
#define _LWIPOPTS_H
|
||||
|
||||
// Generally you would define your own explicit list of lwIP options
|
||||
// (see https://www.nongnu.org/lwip/2_1_x/group__lwip__opts.html)
|
||||
//
|
||||
|
||||
// allow override
|
||||
#ifndef NO_SYS
|
||||
#define NO_SYS 1
|
||||
#endif
|
||||
#ifndef LWIP_SOCKET
|
||||
#define LWIP_SOCKET 0
|
||||
#endif
|
||||
#if PICO_CYW43_ARCH_POLL
|
||||
#define MEM_LIBC_MALLOC 1
|
||||
#else
|
||||
// MEM_LIBC_MALLOC is incompatible with non polling versions
|
||||
#define MEM_LIBC_MALLOC 0
|
||||
#endif
|
||||
#define MEM_ALIGNMENT 4
|
||||
#define MEM_SIZE 4000
|
||||
#define MEMP_NUM_TCP_SEG 32
|
||||
#define MEMP_NUM_ARP_QUEUE 10
|
||||
#define PBUF_POOL_SIZE 24
|
||||
#define LWIP_ARP 1
|
||||
#define LWIP_ETHERNET 1
|
||||
#define LWIP_ICMP 1
|
||||
#define LWIP_RAW 1
|
||||
#define TCP_WND (8 * TCP_MSS)
|
||||
#define TCP_MSS 1460
|
||||
#define TCP_SND_BUF (8 * TCP_MSS)
|
||||
#define TCP_SND_QUEUELEN ((4 * (TCP_SND_BUF) + (TCP_MSS - 1)) / (TCP_MSS))
|
||||
#define LWIP_NETIF_STATUS_CALLBACK 1
|
||||
#define LWIP_NETIF_LINK_CALLBACK 1
|
||||
#define LWIP_NETIF_HOSTNAME 1
|
||||
#define LWIP_NETCONN 0
|
||||
#define MEM_STATS 0
|
||||
#define SYS_STATS 0
|
||||
#define MEMP_STATS 0
|
||||
#define LINK_STATS 0
|
||||
// #define ETH_PAD_SIZE 2
|
||||
#define LWIP_CHKSUM_ALGORITHM 3
|
||||
#define LWIP_DHCP 1
|
||||
#define LWIP_IPV4 1
|
||||
#define LWIP_TCP 1
|
||||
#define LWIP_UDP 1
|
||||
#define LWIP_DNS 1
|
||||
#define LWIP_TCP_KEEPALIVE 1
|
||||
#define LWIP_NETIF_TX_SINGLE_PBUF 1
|
||||
#define DHCP_DOES_ARP_CHECK 0
|
||||
#define LWIP_DHCP_DOES_ACD_CHECK 0
|
||||
|
||||
#ifndef NDEBUG
|
||||
#define LWIP_DEBUG 1
|
||||
#define LWIP_STATS 1
|
||||
#define LWIP_STATS_DISPLAY 1
|
||||
#endif
|
||||
|
||||
#define ETHARP_DEBUG LWIP_DBG_OFF
|
||||
#define NETIF_DEBUG LWIP_DBG_OFF
|
||||
#define PBUF_DEBUG LWIP_DBG_OFF
|
||||
#define API_LIB_DEBUG LWIP_DBG_OFF
|
||||
#define API_MSG_DEBUG LWIP_DBG_OFF
|
||||
#define SOCKETS_DEBUG LWIP_DBG_OFF
|
||||
#define ICMP_DEBUG LWIP_DBG_OFF
|
||||
#define INET_DEBUG LWIP_DBG_OFF
|
||||
#define IP_DEBUG LWIP_DBG_OFF
|
||||
#define IP_REASS_DEBUG LWIP_DBG_OFF
|
||||
#define RAW_DEBUG LWIP_DBG_OFF
|
||||
#define MEM_DEBUG LWIP_DBG_OFF
|
||||
#define MEMP_DEBUG LWIP_DBG_OFF
|
||||
#define SYS_DEBUG LWIP_DBG_OFF
|
||||
#define TCP_DEBUG LWIP_DBG_OFF
|
||||
#define TCP_INPUT_DEBUG LWIP_DBG_OFF
|
||||
#define TCP_OUTPUT_DEBUG LWIP_DBG_OFF
|
||||
#define TCP_RTO_DEBUG LWIP_DBG_OFF
|
||||
#define TCP_CWND_DEBUG LWIP_DBG_OFF
|
||||
#define TCP_WND_DEBUG LWIP_DBG_OFF
|
||||
#define TCP_FR_DEBUG LWIP_DBG_OFF
|
||||
#define TCP_QLEN_DEBUG LWIP_DBG_OFF
|
||||
#define TCP_RST_DEBUG LWIP_DBG_OFF
|
||||
#define UDP_DEBUG LWIP_DBG_OFF
|
||||
#define TCPIP_DEBUG LWIP_DBG_OFF
|
||||
#define PPP_DEBUG LWIP_DBG_OFF
|
||||
#define SLIP_DEBUG LWIP_DBG_OFF
|
||||
#define DHCP_DEBUG LWIP_DBG_OFF
|
||||
|
||||
|
||||
#endif
|
||||
|
114
tusb_config.h
Normal file
114
tusb_config.h
Normal file
@ -0,0 +1,114 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2019 Ha Thach (tinyusb.org)
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _TUSB_CONFIG_H_
|
||||
#define _TUSB_CONFIG_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// COMMON CONFIGURATION
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
// defined by board.mk
|
||||
#ifndef CFG_TUSB_MCU
|
||||
#error CFG_TUSB_MCU must be defined
|
||||
#endif
|
||||
|
||||
// RHPort number used for device can be defined by board.mk, default to port 0
|
||||
#ifndef BOARD_DEVICE_RHPORT_NUM
|
||||
#define BOARD_DEVICE_RHPORT_NUM 0
|
||||
#endif
|
||||
|
||||
// RHPort max operational speed can defined by board.mk
|
||||
// Default to Highspeed for MCU with internal HighSpeed PHY (can be port specific), otherwise FullSpeed
|
||||
#ifndef BOARD_DEVICE_RHPORT_SPEED
|
||||
#if (CFG_TUSB_MCU == OPT_MCU_LPC18XX || CFG_TUSB_MCU == OPT_MCU_LPC43XX || CFG_TUSB_MCU == OPT_MCU_MIMXRT10XX || \
|
||||
CFG_TUSB_MCU == OPT_MCU_NUC505 || CFG_TUSB_MCU == OPT_MCU_CXD56 || CFG_TUSB_MCU == OPT_MCU_SAMX7X)
|
||||
#define BOARD_DEVICE_RHPORT_SPEED OPT_MODE_HIGH_SPEED
|
||||
#else
|
||||
#define BOARD_DEVICE_RHPORT_SPEED OPT_MODE_FULL_SPEED
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Device mode with rhport and speed defined by board.mk
|
||||
#if BOARD_DEVICE_RHPORT_NUM == 0
|
||||
#define CFG_TUSB_RHPORT0_MODE (OPT_MODE_DEVICE | BOARD_DEVICE_RHPORT_SPEED)
|
||||
#elif BOARD_DEVICE_RHPORT_NUM == 1
|
||||
#define CFG_TUSB_RHPORT1_MODE (OPT_MODE_DEVICE | BOARD_DEVICE_RHPORT_SPEED)
|
||||
#else
|
||||
#error "Incorrect RHPort configuration"
|
||||
#endif
|
||||
|
||||
#ifndef CFG_TUSB_OS
|
||||
#define CFG_TUSB_OS OPT_OS_NONE
|
||||
#endif
|
||||
|
||||
// CFG_TUSB_DEBUG is defined by compiler in DEBUG build
|
||||
// #define CFG_TUSB_DEBUG 0
|
||||
|
||||
/* USB DMA on some MCUs can only access a specific SRAM region with restriction on alignment.
|
||||
* Tinyusb use follows macros to declare transferring memory so that they can be put
|
||||
* into those specific section.
|
||||
* e.g
|
||||
* - CFG_TUSB_MEM SECTION : __attribute__ (( section(".usb_ram") ))
|
||||
* - CFG_TUSB_MEM_ALIGN : __attribute__ ((aligned(4)))
|
||||
*/
|
||||
#ifndef CFG_TUSB_MEM_SECTION
|
||||
#define CFG_TUSB_MEM_SECTION
|
||||
#endif
|
||||
|
||||
#ifndef CFG_TUSB_MEM_ALIGN
|
||||
#define CFG_TUSB_MEM_ALIGN __attribute__ ((aligned(4)))
|
||||
#endif
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// DEVICE CONFIGURATION
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
#ifndef CFG_TUD_ENDPOINT0_SIZE
|
||||
#define CFG_TUD_ENDPOINT0_SIZE 64
|
||||
#endif
|
||||
|
||||
//------------- CLASS -------------//
|
||||
#define CFG_TUD_HID 0
|
||||
#define CFG_TUD_CDC 1
|
||||
#define CFG_TUD_MSC 0
|
||||
#define CFG_TUD_MIDI 0
|
||||
#define CFG_TUD_VENDOR 0
|
||||
|
||||
//------------- CDC -------------//
|
||||
|
||||
// CDC buffer size Should be sufficient to hold data
|
||||
#define CFG_TUD_CDC_RX_BUFSIZE 16
|
||||
#define CFG_TUD_CDC_TX_BUFSIZE 16
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _TUSB_CONFIG_H_ */
|
248
vga/businterface.c
Normal file
248
vga/businterface.c
Normal file
@ -0,0 +1,248 @@
|
||||
#include <string.h>
|
||||
#include <hardware/pio.h>
|
||||
#include "common/config.h"
|
||||
#include "common/abus.h"
|
||||
#include "vga/businterface.h"
|
||||
#include "vga/vgabuf.h"
|
||||
|
||||
volatile uint8_t *terminal_page = terminal_memory;
|
||||
|
||||
void __time_critical_func(vga_businterface)(uint32_t address, uint32_t value) {
|
||||
// Shadow the soft-switches by observing all read & write bus cycles
|
||||
if((address & 0xff80) == 0xc000) {
|
||||
switch(address & 0x7f) {
|
||||
case 0x00:
|
||||
if((internal_flags & (IFLAGS_IIGS_REGS | IFLAGS_IIE_REGS)) && ((value & (1u << CONFIG_PIN_APPLEBUS_RW-CONFIG_PIN_APPLEBUS_DATA_BASE)) == 0)) {
|
||||
soft_switches &= ~SOFTSW_80STORE;
|
||||
}
|
||||
break;
|
||||
case 0x01:
|
||||
if((internal_flags & (IFLAGS_IIGS_REGS | IFLAGS_IIE_REGS)) && ((value & (1u << CONFIG_PIN_APPLEBUS_RW-CONFIG_PIN_APPLEBUS_DATA_BASE)) == 0)) {
|
||||
soft_switches |= SOFTSW_80STORE;
|
||||
}
|
||||
break;
|
||||
case 0x04:
|
||||
if((internal_flags & (IFLAGS_IIGS_REGS | IFLAGS_IIE_REGS)) && ((value & (1u << CONFIG_PIN_APPLEBUS_RW-CONFIG_PIN_APPLEBUS_DATA_BASE)) == 0)) {
|
||||
soft_switches &= ~SOFTSW_AUX_WRITE;
|
||||
}
|
||||
break;
|
||||
case 0x05:
|
||||
if((internal_flags & (IFLAGS_IIGS_REGS | IFLAGS_IIE_REGS)) && ((value & (1u << CONFIG_PIN_APPLEBUS_RW-CONFIG_PIN_APPLEBUS_DATA_BASE)) == 0)) {
|
||||
soft_switches |= SOFTSW_AUX_WRITE;
|
||||
}
|
||||
break;
|
||||
case 0x08:
|
||||
if((internal_flags & (IFLAGS_IIGS_REGS | IFLAGS_IIE_REGS)) && ((value & (1u << CONFIG_PIN_APPLEBUS_RW-CONFIG_PIN_APPLEBUS_DATA_BASE)) == 0)) {
|
||||
soft_switches &= ~SOFTSW_AUXZP;
|
||||
}
|
||||
break;
|
||||
case 0x09:
|
||||
if((internal_flags & (IFLAGS_IIGS_REGS | IFLAGS_IIE_REGS)) && ((value & (1u << CONFIG_PIN_APPLEBUS_RW-CONFIG_PIN_APPLEBUS_DATA_BASE)) == 0)) {
|
||||
soft_switches |= SOFTSW_AUXZP;
|
||||
}
|
||||
break;
|
||||
case 0x0c:
|
||||
if((internal_flags & (IFLAGS_IIGS_REGS | IFLAGS_IIE_REGS)) && ((value & (1u << CONFIG_PIN_APPLEBUS_RW-CONFIG_PIN_APPLEBUS_DATA_BASE)) == 0)) {
|
||||
soft_switches &= ~SOFTSW_80COL;
|
||||
}
|
||||
break;
|
||||
case 0x0d:
|
||||
if((internal_flags & (IFLAGS_IIGS_REGS | IFLAGS_IIE_REGS)) && ((value & (1u << CONFIG_PIN_APPLEBUS_RW-CONFIG_PIN_APPLEBUS_DATA_BASE)) == 0)) {
|
||||
soft_switches |= SOFTSW_80COL;
|
||||
}
|
||||
break;
|
||||
case 0x0e:
|
||||
if((internal_flags & (IFLAGS_IIGS_REGS | IFLAGS_IIE_REGS)) && ((value & (1u << CONFIG_PIN_APPLEBUS_RW-CONFIG_PIN_APPLEBUS_DATA_BASE)) == 0)) {
|
||||
soft_switches &= ~SOFTSW_ALTCHAR;
|
||||
}
|
||||
break;
|
||||
case 0x0f:
|
||||
if((internal_flags & (IFLAGS_IIGS_REGS | IFLAGS_IIE_REGS)) && ((value & (1u << CONFIG_PIN_APPLEBUS_RW-CONFIG_PIN_APPLEBUS_DATA_BASE)) == 0)) {
|
||||
soft_switches |= SOFTSW_ALTCHAR;
|
||||
}
|
||||
break;
|
||||
case 0x21:
|
||||
if((internal_flags & (IFLAGS_IIGS_REGS | IFLAGS_IIE_REGS)) && ((value & (1u << CONFIG_PIN_APPLEBUS_RW-CONFIG_PIN_APPLEBUS_DATA_BASE)) == 0)) {
|
||||
if(value & 0x80) {
|
||||
soft_switches |= SOFTSW_MONOCHROME;
|
||||
} else {
|
||||
soft_switches &= ~SOFTSW_MONOCHROME;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 0x22:
|
||||
if((internal_flags & IFLAGS_IIGS_REGS) && ((value & (1u << CONFIG_PIN_APPLEBUS_RW-CONFIG_PIN_APPLEBUS_DATA_BASE)) == 0)) {
|
||||
apple_tbcolor = value & 0xff;
|
||||
}
|
||||
break;
|
||||
case 0x29:
|
||||
if((internal_flags & IFLAGS_IIGS_REGS) && ((value & (1u << CONFIG_PIN_APPLEBUS_RW-CONFIG_PIN_APPLEBUS_DATA_BASE)) == 0)) {
|
||||
soft_switches = (soft_switches & ~(SOFTSW_NEWVID_MASK << SOFTSW_NEWVID_SHIFT)) | ((value & SOFTSW_NEWVID_MASK) << SOFTSW_NEWVID_SHIFT);
|
||||
}
|
||||
break;
|
||||
case 0x34:
|
||||
if((internal_flags & IFLAGS_IIGS_REGS) && ((value & (1u << CONFIG_PIN_APPLEBUS_RW-CONFIG_PIN_APPLEBUS_DATA_BASE)) == 0)) {
|
||||
apple_border = value & 0x0f;
|
||||
}
|
||||
break;
|
||||
case 0x35:
|
||||
if((internal_flags & IFLAGS_IIGS_REGS) && ((value & (1u << CONFIG_PIN_APPLEBUS_RW-CONFIG_PIN_APPLEBUS_DATA_BASE)) == 0)) {
|
||||
soft_switches = (soft_switches & ~(SOFTSW_SHADOW_MASK << SOFTSW_SHADOW_SHIFT)) | ((value & SOFTSW_SHADOW_MASK) << SOFTSW_SHADOW_SHIFT);
|
||||
}
|
||||
break;
|
||||
case 0x50:
|
||||
soft_switches &= ~SOFTSW_TEXT_MODE;
|
||||
break;
|
||||
case 0x51:
|
||||
soft_switches |= SOFTSW_TEXT_MODE;
|
||||
break;
|
||||
case 0x52:
|
||||
soft_switches &= ~SOFTSW_MIX_MODE;
|
||||
break;
|
||||
case 0x53:
|
||||
soft_switches |= SOFTSW_MIX_MODE;
|
||||
break;
|
||||
case 0x54:
|
||||
soft_switches &= ~SOFTSW_PAGE_2;
|
||||
break;
|
||||
case 0x55:
|
||||
soft_switches |= SOFTSW_PAGE_2;
|
||||
break;
|
||||
case 0x56:
|
||||
soft_switches &= ~SOFTSW_HIRES_MODE;
|
||||
break;
|
||||
case 0x57:
|
||||
soft_switches |= SOFTSW_HIRES_MODE;
|
||||
break;
|
||||
case 0x5e:
|
||||
if(internal_flags & (IFLAGS_IIGS_REGS | IFLAGS_IIE_REGS)) {
|
||||
soft_switches |= SOFTSW_DGR;
|
||||
}
|
||||
break;
|
||||
case 0x5f:
|
||||
if(internal_flags & (IFLAGS_IIGS_REGS | IFLAGS_IIE_REGS)) {
|
||||
soft_switches &= ~SOFTSW_DGR;
|
||||
}
|
||||
break;
|
||||
case 0x7e:
|
||||
if((internal_flags & IFLAGS_IIE_REGS) && ((value & (1u << CONFIG_PIN_APPLEBUS_RW-CONFIG_PIN_APPLEBUS_DATA_BASE)) == 0)) {
|
||||
soft_switches |= SOFTSW_IOUDIS;
|
||||
}
|
||||
break;
|
||||
case 0x7f:
|
||||
if((internal_flags & IFLAGS_IIE_REGS) && ((value & (1u << CONFIG_PIN_APPLEBUS_RW-CONFIG_PIN_APPLEBUS_DATA_BASE)) == 0)) {
|
||||
soft_switches &= ~SOFTSW_IOUDIS;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Control sequences used by ROMX and ROMXe
|
||||
if(value & (1u << CONFIG_PIN_APPLEBUS_RW-CONFIG_PIN_APPLEBUS_DATA_BASE)) {
|
||||
if(((address >> 8) == 0xCA) || ((address >> 8) == 0xFA)) {
|
||||
switch(address & 0xFF) {
|
||||
case 0xCA:
|
||||
romx_unlocked = (romx_unlocked == 1) ? 2 : 1;
|
||||
break;
|
||||
case 0xFE:
|
||||
romx_unlocked = (romx_unlocked == 2) ? 3 : 0;
|
||||
if(romx_unlocked == 3)
|
||||
romx_type = address >> 8;
|
||||
break;
|
||||
default:
|
||||
if(romx_unlocked != 3)
|
||||
romx_unlocked = 0;
|
||||
break;
|
||||
}
|
||||
} else if(romx_unlocked == 3) {
|
||||
if(romx_type == 0xFA) {
|
||||
if((address >> 4) == 0xF81) {
|
||||
romx_textbank = address & 0xF;
|
||||
}
|
||||
if(address == 0xF851) {
|
||||
romx_changed = 1;
|
||||
romx_unlocked = 0;
|
||||
}
|
||||
} else if(romx_type == 0xCA) {
|
||||
if((address >> 4) == 0xCFD) {
|
||||
romx_textbank = address & 0xF;
|
||||
}
|
||||
if((address >> 4) == 0xCFE) {
|
||||
romx_changed = 1;
|
||||
romx_unlocked = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Shadow parts of the Apple's memory by observing the bus write cycles
|
||||
if((value & (1u << CONFIG_PIN_APPLEBUS_RW-CONFIG_PIN_APPLEBUS_DATA_BASE)) == 0) {
|
||||
// Mirror Video Memory from MAIN & AUX banks
|
||||
if(soft_switches & SOFTSW_LINEARIZE) {
|
||||
if((address >= 0x2000) && (address < 0xC000)) {
|
||||
private_memory[address] = value & 0xff;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if(soft_switches & SOFTSW_80STORE) {
|
||||
if(soft_switches & SOFTSW_PAGE_2) {
|
||||
if((address >= 0x400) && (address < 0x800)) {
|
||||
private_memory[address] = value & 0xff;
|
||||
return;
|
||||
} else if((soft_switches & SOFTSW_HIRES_MODE) && (address >= 0x2000) && (address < 0x4000)) {
|
||||
private_memory[address] = value & 0xff;
|
||||
return;
|
||||
}
|
||||
}
|
||||
} else if(soft_switches & SOFTSW_AUX_WRITE) {
|
||||
if((address >= 0x200) && (address < 0xC000)) {
|
||||
private_memory[address] = value & 0xff;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if((address >= 0x200) && (address < 0xC000)) {
|
||||
apple_memory[address] = value & 0xff;
|
||||
return;
|
||||
}
|
||||
|
||||
if(CARD_SELECT && CARD_DEVSEL) {
|
||||
cardslot = (address >> 4) & 0x7;
|
||||
switch(address & 0x0F) {
|
||||
case 0x01:
|
||||
mono_palette = (value >> 4) & 0xF;
|
||||
apple_memory[address] = value;
|
||||
break;
|
||||
case 0x02:
|
||||
terminal_tbcolor = value & 0xff;
|
||||
apple_memory[address] = terminal_tbcolor;
|
||||
break;
|
||||
case 0x03:
|
||||
terminal_border = value & 0x0f;
|
||||
apple_memory[address] = terminal_border;
|
||||
break;
|
||||
case 0x08:
|
||||
terminal_row = (value < 24) ? value : 23;
|
||||
apple_memory[address] = terminal_row;
|
||||
apple_memory[address+2] = terminal_memory[terminal_row*80+terminal_col];
|
||||
break;
|
||||
case 0x09:
|
||||
terminal_col = (value < 80) ? value : 79;
|
||||
apple_memory[address] = terminal_col;
|
||||
apple_memory[address+1] = terminal_memory[terminal_row*80+terminal_col];
|
||||
break;
|
||||
case 0x0A:
|
||||
terminal_memory[terminal_row*80+terminal_col] = value;
|
||||
break;
|
||||
case 0x0B:
|
||||
if(value <= 0x27) {
|
||||
romx_textbank = value;
|
||||
romx_changed = 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
3
vga/businterface.h
Normal file
3
vga/businterface.h
Normal file
@ -0,0 +1,3 @@
|
||||
#pragma once
|
||||
|
||||
void vga_businterface();
|
525
vga/hires_color_patterns.h
Normal file
525
vga/hires_color_patterns.h
Normal file
@ -0,0 +1,525 @@
|
||||
#pragma once
|
||||
|
||||
#include "common/config.h"
|
||||
#include "vga/render.h"
|
||||
|
||||
#define _PIXELS(color1, color2) ((uint32_t)(color1) | ((uint32_t)(color2) << 16))
|
||||
|
||||
static uint32_t DELAYED_COPY_DATA(hires_color_patterns)[2*256] = {
|
||||
// Even byte pixels
|
||||
/* 0b00000000 */ _PIXELS(RGB_BLACK, RGB_BLACK),
|
||||
/* 0b00000001 */ _PIXELS(RGB_BLACK, RGB_BLACK),
|
||||
/* 0b00000010 */ _PIXELS(RGB_BLACK, RGB_BLACK),
|
||||
/* 0b00000011 */ _PIXELS(RGB_BLACK, RGB_BLACK),
|
||||
/* 0b00000100 */ _PIXELS(RGB_BLACK, RGB_BLACK),
|
||||
/* 0b00000101 */ _PIXELS(RGB_BLACK, RGB_BLACK),
|
||||
/* 0b00000110 */ _PIXELS(RGB_BLACK, RGB_BLACK),
|
||||
/* 0b00000111 */ _PIXELS(RGB_BLACK, RGB_BLACK),
|
||||
/* 0b00001000 */ _PIXELS(RGB_BLACK, RGB_DBLUE),
|
||||
/* 0b00001001 */ _PIXELS(RGB_BLACK, _RGB(0x90, 0x24, 0xD8)),
|
||||
/* 0b00001010 */ _PIXELS(RGB_BLACK, _RGB(0x90, 0x90, 0x90)),
|
||||
/* 0b00001011 */ _PIXELS(RGB_BLACK, _RGB(0xD8, 0x6C, 0xD8)),
|
||||
/* 0b00001100 */ _PIXELS(RGB_BLACK, _RGB(0x00, 0x90, 0xFC)),
|
||||
/* 0b00001101 */ _PIXELS(RGB_BLACK, _RGB(0x48, 0x6C, 0xFC)),
|
||||
/* 0b00001110 */ _PIXELS(RGB_BLACK, _RGB(0x90, 0xFC, 0xB4)),
|
||||
/* 0b00001111 */ _PIXELS(RGB_BLACK, RGB_WHITE),
|
||||
/* 0b00010000 */ _PIXELS(_RGB(0x6C, 0x00, 0x6C), RGB_BLACK),
|
||||
/* 0b00010001 */ _PIXELS(_RGB(0x6C, 0x00, 0x6C), _RGB(0x6C, 0x00, 0x6C)),
|
||||
/* 0b00010010 */ _PIXELS(_RGB(0xD8, 0x24, 0x24), _RGB(0xFC, 0x48, 0x00)),
|
||||
/* 0b00010011 */ _PIXELS(_RGB(0xD8, 0x24, 0x24), _RGB(0xFC, 0x48, 0x00)),
|
||||
/* 0b00010100 */ _PIXELS(_RGB(0x48, 0x48, 0x48), _RGB(0x48, 0x48, 0x48)),
|
||||
/* 0b00010101 */ _PIXELS(_RGB(0x48, 0x48, 0x48), _RGB(0x48, 0x48, 0x48)),
|
||||
/* 0b00010110 */ _PIXELS(_RGB(0xB4, 0xB4, 0x24), _RGB(0xD8, 0xD8, 0x00)),
|
||||
/* 0b00010111 */ _PIXELS(_RGB(0xB4, 0xB4, 0x24), _RGB(0xD8, 0xD8, 0x00)),
|
||||
/* 0b00011000 */ _PIXELS(_RGB(0xB4, 0x24, 0xFC), _RGB(0xB4, 0x24, 0xFC)),
|
||||
/* 0b00011001 */ _PIXELS(_RGB(0xB4, 0x24, 0xFC), _RGB(0xB4, 0x24, 0xFC)),
|
||||
/* 0b00011010 */ _PIXELS(_RGB(0xD8, 0x48, 0xFC), RGB_PINK),
|
||||
/* 0b00011011 */ _PIXELS(_RGB(0xD8, 0x48, 0xFC), RGB_PINK),
|
||||
/* 0b00011100 */ _PIXELS(_RGB(0x6C, 0x6C, 0xFC), _RGB(0x6C, 0x6C, 0xFC)),
|
||||
/* 0b00011101 */ _PIXELS(_RGB(0x6C, 0x6C, 0xFC), _RGB(0x6C, 0x6C, 0xFC)),
|
||||
/* 0b00011110 */ _PIXELS(RGB_WHITE, RGB_WHITE),
|
||||
/* 0b00011111 */ _PIXELS(RGB_WHITE, RGB_WHITE),
|
||||
/* 0b00100000 */ _PIXELS(RGB_BLACK, RGB_BLACK),
|
||||
/* 0b00100001 */ _PIXELS(RGB_BLACK, RGB_BLACK),
|
||||
/* 0b00100010 */ _PIXELS(_RGB(0x24, 0x24, 0x00), _RGB(0x24, 0x24, 0x00)),
|
||||
/* 0b00100011 */ _PIXELS(_RGB(0x24, 0x24, 0x00), _RGB(0xB4, 0x48, 0x00)),
|
||||
/* 0b00100100 */ _PIXELS(_RGB(0x00, 0x6C, 0x00), RGB_DGREEN),
|
||||
/* 0b00100101 */ _PIXELS(_RGB(0x00, 0x6C, 0x00), _RGB(0x24, 0x48, 0x48)),
|
||||
/* 0b00100110 */ _PIXELS(_RGB(0x00, 0xD8, 0x24), _RGB(0x00, 0xD8, 0x24)),
|
||||
/* 0b00100111 */ _PIXELS(_RGB(0x00, 0xD8, 0x24), _RGB(0x90, 0xD8, 0x00)),
|
||||
/* 0b00101000 */ _PIXELS(_RGB(0x24, 0x24, 0xB4), RGB_DBLUE),
|
||||
/* 0b00101001 */ _PIXELS(_RGB(0x24, 0x24, 0xB4), _RGB(0x90, 0x24, 0xD8)),
|
||||
/* 0b00101010 */ _PIXELS(_RGB(0x90, 0x90, 0x90), _RGB(0x90, 0x90, 0x90)),
|
||||
/* 0b00101011 */ _PIXELS(_RGB(0x90, 0x90, 0x90), _RGB(0xD8, 0x6C, 0xD8)),
|
||||
/* 0b00101100 */ _PIXELS(_RGB(0x24, 0xB4, 0xD8), _RGB(0x00, 0x90, 0xFC)),
|
||||
/* 0b00101101 */ _PIXELS(_RGB(0x24, 0xB4, 0xD8), _RGB(0x48, 0x6C, 0xFC)),
|
||||
/* 0b00101110 */ _PIXELS(_RGB(0x90, 0xFC, 0xB4), _RGB(0x90, 0xFC, 0xB4)),
|
||||
/* 0b00101111 */ _PIXELS(_RGB(0x90, 0xFC, 0xB4), RGB_WHITE),
|
||||
/* 0b00110000 */ _PIXELS(_RGB(0x90, 0x24, 0x48), RGB_BLACK),
|
||||
/* 0b00110001 */ _PIXELS(_RGB(0x90, 0x24, 0x48), _RGB(0x6C, 0x00, 0x6C)),
|
||||
/* 0b00110010 */ _PIXELS(_RGB(0xFC, 0x48, 0x00), _RGB(0xFC, 0x48, 0x00)),
|
||||
/* 0b00110011 */ _PIXELS(_RGB(0xFC, 0x48, 0x00), _RGB(0xFC, 0x48, 0x00)),
|
||||
/* 0b00110100 */ _PIXELS(_RGB(0x6C, 0x6C, 0x24), _RGB(0x48, 0x48, 0x48)),
|
||||
/* 0b00110101 */ _PIXELS(_RGB(0x6C, 0x6C, 0x24), _RGB(0x48, 0x48, 0x48)),
|
||||
/* 0b00110110 */ _PIXELS(_RGB(0xD8, 0xD8, 0x00), _RGB(0xD8, 0xD8, 0x00)),
|
||||
/* 0b00110111 */ _PIXELS(_RGB(0xD8, 0xD8, 0x00), _RGB(0xD8, 0xD8, 0x00)),
|
||||
/* 0b00111000 */ _PIXELS(_RGB(0xB4, 0x48, 0xFC), _RGB(0xB4, 0x24, 0xFC)),
|
||||
/* 0b00111001 */ _PIXELS(_RGB(0xB4, 0x48, 0xFC), _RGB(0xB4, 0x24, 0xFC)),
|
||||
/* 0b00111010 */ _PIXELS(RGB_PINK, RGB_PINK),
|
||||
/* 0b00111011 */ _PIXELS(RGB_PINK, RGB_PINK),
|
||||
/* 0b00111100 */ _PIXELS(RGB_WHITE, RGB_WHITE),
|
||||
/* 0b00111101 */ _PIXELS(RGB_WHITE, RGB_WHITE),
|
||||
/* 0b00111110 */ _PIXELS(RGB_WHITE, RGB_WHITE),
|
||||
/* 0b00111111 */ _PIXELS(RGB_WHITE, RGB_WHITE),
|
||||
/* 0b01000000 */ _PIXELS(RGB_BLACK, RGB_BLACK),
|
||||
/* 0b01000001 */ _PIXELS(RGB_BLACK, RGB_BLACK),
|
||||
/* 0b01000010 */ _PIXELS(RGB_BLACK, RGB_BLACK),
|
||||
/* 0b01000011 */ _PIXELS(RGB_BLACK, RGB_BLACK),
|
||||
/* 0b01000100 */ _PIXELS(RGB_DGREEN, RGB_DGREEN),
|
||||
/* 0b01000101 */ _PIXELS(RGB_DGREEN, _RGB(0x24, 0x48, 0x24)),
|
||||
/* 0b01000110 */ _PIXELS(_RGB(0x00, 0xB4, 0x24), _RGB(0x00, 0xD8, 0x24)),
|
||||
/* 0b01000111 */ _PIXELS(_RGB(0x00, 0xB4, 0x24), _RGB(0x90, 0xD8, 0x00)),
|
||||
/* 0b01001000 */ _PIXELS(_RGB(0x00, 0x24, 0xB4), RGB_DBLUE),
|
||||
/* 0b01001001 */ _PIXELS(_RGB(0x00, 0x24, 0xB4), _RGB(0x90, 0x24, 0xFC)),
|
||||
/* 0b01001010 */ _PIXELS(_RGB(0x6C, 0x90, 0xB4), _RGB(0x90, 0x90, 0x90)),
|
||||
/* 0b01001011 */ _PIXELS(_RGB(0x6C, 0x90, 0xB4), _RGB(0xD8, 0x6C, 0xD8)),
|
||||
/* 0b01001100 */ _PIXELS(_RGB(0x00, 0x90, 0xFC), _RGB(0x00, 0x90, 0xFC)),
|
||||
/* 0b01001101 */ _PIXELS(_RGB(0x00, 0x90, 0xFC), _RGB(0x48, 0x6C, 0xFC)),
|
||||
/* 0b01001110 */ _PIXELS(_RGB(0x6C, 0xD8, 0xB4), _RGB(0x90, 0xFC, 0xB4)),
|
||||
/* 0b01001111 */ _PIXELS(_RGB(0x6C, 0xD8, 0xB4), RGB_WHITE),
|
||||
/* 0b01010000 */ _PIXELS(_RGB(0x6C, 0x24, 0x6C), RGB_BLACK),
|
||||
/* 0b01010001 */ _PIXELS(_RGB(0x6C, 0x24, 0x6C), _RGB(0x6C, 0x00, 0x6C)),
|
||||
/* 0b01010010 */ _PIXELS(_RGB(0xD8, 0x48, 0x24), _RGB(0xFC, 0x48, 0x00)),
|
||||
/* 0b01010011 */ _PIXELS(_RGB(0xD8, 0x48, 0x24), _RGB(0xFC, 0x48, 0x00)),
|
||||
/* 0b01010100 */ _PIXELS(_RGB(0x48, 0x48, 0x48), _RGB(0x48, 0x48, 0x48)),
|
||||
/* 0b01010101 */ _PIXELS(_RGB(0x48, 0x48, 0x48), _RGB(0x48, 0x48, 0x48)),
|
||||
/* 0b01010110 */ _PIXELS(_RGB(0xB4, 0xB4, 0x24), _RGB(0xD8, 0xD8, 0x00)),
|
||||
/* 0b01010111 */ _PIXELS(_RGB(0xB4, 0xB4, 0x24), _RGB(0xD8, 0xD8, 0x00)),
|
||||
/* 0b01011000 */ _PIXELS(_RGB(0x90, 0x48, 0xFC), _RGB(0xB4, 0x24, 0xFC)),
|
||||
/* 0b01011001 */ _PIXELS(_RGB(0x90, 0x48, 0xFC), _RGB(0xB4, 0x24, 0xFC)),
|
||||
/* 0b01011010 */ _PIXELS(_RGB(0xD8, 0x6C, 0xFC), RGB_PINK),
|
||||
/* 0b01011011 */ _PIXELS(_RGB(0xD8, 0x6C, 0xFC), RGB_PINK),
|
||||
/* 0b01011100 */ _PIXELS(_RGB(0x6C, 0x6C, 0xFC), _RGB(0x6C, 0x6C, 0xFC)),
|
||||
/* 0b01011101 */ _PIXELS(_RGB(0x6C, 0x6C, 0xFC), _RGB(0x6C, 0x6C, 0xFC)),
|
||||
/* 0b01011110 */ _PIXELS(RGB_WHITE, RGB_WHITE),
|
||||
/* 0b01011111 */ _PIXELS(RGB_WHITE, RGB_WHITE),
|
||||
/* 0b01100000 */ _PIXELS(RGB_BLACK, RGB_BLACK),
|
||||
/* 0b01100001 */ _PIXELS(RGB_BLACK, RGB_BLACK),
|
||||
/* 0b01100010 */ _PIXELS(_RGB(0x24, 0x48, 0x00), _RGB(0x24, 0x24, 0x00)),
|
||||
/* 0b01100011 */ _PIXELS(_RGB(0x24, 0x48, 0x00), _RGB(0xB4, 0x48, 0x00)),
|
||||
/* 0b01100100 */ _PIXELS(_RGB(0x00, 0x6C, 0x00), RGB_DGREEN),
|
||||
/* 0b01100101 */ _PIXELS(_RGB(0x00, 0x6C, 0x00), _RGB(0x24, 0x48, 0x48)),
|
||||
/* 0b01100110 */ _PIXELS(_RGB(0x00, 0xD8, 0x24), _RGB(0x00, 0xD8, 0x24)),
|
||||
/* 0b01100111 */ _PIXELS(_RGB(0x00, 0xD8, 0x24), _RGB(0x90, 0xD8, 0x00)),
|
||||
/* 0b01101000 */ _PIXELS(_RGB(0x24, 0x48, 0xB4), _RGB(0x00, 0x24, 0xB4)),
|
||||
/* 0b01101001 */ _PIXELS(_RGB(0x24, 0x48, 0xB4), _RGB(0x90, 0x24, 0xD8)),
|
||||
/* 0b01101010 */ _PIXELS(_RGB(0x90, 0xB4, 0x90), _RGB(0x90, 0x90, 0x90)),
|
||||
/* 0b01101011 */ _PIXELS(_RGB(0x90, 0xB4, 0x90), _RGB(0xD8, 0x6C, 0xD8)),
|
||||
/* 0b01101100 */ _PIXELS(_RGB(0x24, 0xB4, 0xD8), _RGB(0x00, 0x90, 0xFC)),
|
||||
/* 0b01101101 */ _PIXELS(_RGB(0x24, 0xB4, 0xD8), _RGB(0x48, 0x6C, 0xFC)),
|
||||
/* 0b01101110 */ _PIXELS(_RGB(0x90, 0xFC, 0xB4), _RGB(0x90, 0xFC, 0xB4)),
|
||||
/* 0b01101111 */ _PIXELS(_RGB(0x90, 0xFC, 0xB4), RGB_WHITE),
|
||||
/* 0b01110000 */ _PIXELS(_RGB(0x90, 0x48, 0x48), RGB_BLACK),
|
||||
/* 0b01110001 */ _PIXELS(0x112, _RGB(0x6C, 0x00, 0x6C)),
|
||||
/* 0b01110010 */ _PIXELS(_RGB(0xFC, 0x6C, 0x00), _RGB(0xFC, 0x48, 0x00)),
|
||||
/* 0b01110011 */ _PIXELS(_RGB(0xFC, 0x6C, 0x00), _RGB(0xFC, 0x48, 0x00)),
|
||||
/* 0b01110100 */ _PIXELS(_RGB(0x6C, 0x6C, 0x24), _RGB(0x48, 0x48, 0x48)),
|
||||
/* 0b01110101 */ _PIXELS(_RGB(0x6C, 0x6C, 0x24), _RGB(0x48, 0x48, 0x48)),
|
||||
/* 0b01110110 */ _PIXELS(_RGB(0xD8, 0xD8, 0x00), _RGB(0xD8, 0xD8, 0x00)),
|
||||
/* 0b01110111 */ _PIXELS(_RGB(0xD8, 0xD8, 0x00), _RGB(0xD8, 0xD8, 0x00)),
|
||||
/* 0b01111000 */ _PIXELS(RGB_WHITE, RGB_WHITE),
|
||||
/* 0b01111001 */ _PIXELS(RGB_WHITE, RGB_WHITE),
|
||||
/* 0b01111010 */ _PIXELS(RGB_WHITE, RGB_WHITE),
|
||||
/* 0b01111011 */ _PIXELS(RGB_WHITE, RGB_WHITE),
|
||||
/* 0b01111100 */ _PIXELS(RGB_WHITE, RGB_WHITE),
|
||||
/* 0b01111101 */ _PIXELS(RGB_WHITE, RGB_WHITE),
|
||||
/* 0b01111110 */ _PIXELS(RGB_WHITE, RGB_WHITE),
|
||||
/* 0b01111111 */ _PIXELS(RGB_WHITE, RGB_WHITE),
|
||||
/* 0b10000000 */ _PIXELS(RGB_BLACK, RGB_BLACK),
|
||||
/* 0b10000001 */ _PIXELS(RGB_BLACK, RGB_BLACK),
|
||||
/* 0b10000010 */ _PIXELS(RGB_BLACK, RGB_BLACK),
|
||||
/* 0b10000011 */ _PIXELS(RGB_BLACK, RGB_BLACK),
|
||||
/* 0b10000100 */ _PIXELS(RGB_BLACK, RGB_BLACK),
|
||||
/* 0b10000101 */ _PIXELS(RGB_BLACK, RGB_BLACK),
|
||||
/* 0b10000110 */ _PIXELS(RGB_BLACK, RGB_BLACK),
|
||||
/* 0b10000111 */ _PIXELS(RGB_BLACK, RGB_BLACK),
|
||||
/* 0b10001000 */ _PIXELS(RGB_DBLUE, RGB_DBLUE),
|
||||
/* 0b10001001 */ _PIXELS(RGB_DBLUE, _RGB(0x90, 0x24, 0xD8)),
|
||||
/* 0b10001010 */ _PIXELS(_RGB(0x6C, 0x6C, 0x90), _RGB(0x90, 0x90, 0x90)),
|
||||
/* 0b10001011 */ _PIXELS(_RGB(0x6C, 0x6C, 0x90), _RGB(0xD8, 0x6C, 0xD8)),
|
||||
/* 0b10001100 */ _PIXELS(_RGB(0x00, 0x90, 0xFC), _RGB(0x00, 0x90, 0xFC)),
|
||||
/* 0b10001101 */ _PIXELS(_RGB(0x00, 0x90, 0xFC), _RGB(0x48, 0x6C, 0xFC)),
|
||||
/* 0b10001110 */ _PIXELS(_RGB(0x6C, 0xD8, 0xB4), _RGB(0x90, 0xFC, 0xB4)),
|
||||
/* 0b10001111 */ _PIXELS(_RGB(0x6C, 0xD8, 0xB4), RGB_WHITE),
|
||||
/* 0b10010000 */ _PIXELS(_RGB(0x6C, 0x00, 0x90), RGB_BLACK),
|
||||
/* 0b10010001 */ _PIXELS(_RGB(0x6C, 0x00, 0x90), _RGB(0x6C, 0x00, 0x6C)),
|
||||
/* 0b10010010 */ _PIXELS(_RGB(0xD8, 0x48, 0x48), _RGB(0xFC, 0x48, 0x00)),
|
||||
/* 0b10010011 */ _PIXELS(_RGB(0xD8, 0x48, 0x48), _RGB(0xFC, 0x48, 0x00)),
|
||||
/* 0b10010100 */ _PIXELS(_RGB(0x48, 0x48, 0x6C), _RGB(0x48, 0x48, 0x48)),
|
||||
/* 0b10010101 */ _PIXELS(_RGB(0x48, 0x48, 0x6C), _RGB(0x48, 0x48, 0x48)),
|
||||
/* 0b10010110 */ _PIXELS(_RGB(0xB4, 0xB4, 0x48), _RGB(0xD8, 0xD8, 0x00)),
|
||||
/* 0b10010111 */ _PIXELS(_RGB(0xB4, 0xB4, 0x48), _RGB(0xD8, 0xD8, 0x00)),
|
||||
/* 0b10011000 */ _PIXELS(_RGB(0xB4, 0x24, 0xFC), _RGB(0xB4, 0x24, 0xFC)),
|
||||
/* 0b10011001 */ _PIXELS(_RGB(0xB4, 0x24, 0xFC), _RGB(0xB4, 0x24, 0xFC)),
|
||||
/* 0b10011010 */ _PIXELS(_RGB(0xD8, 0x48, 0xFC), RGB_PINK),
|
||||
/* 0b10011011 */ _PIXELS(_RGB(0xD8, 0x48, 0xFC), RGB_PINK),
|
||||
/* 0b10011100 */ _PIXELS(_RGB(0x6C, 0x6C, 0xFC), _RGB(0x6C, 0x6C, 0xFC)),
|
||||
/* 0b10011101 */ _PIXELS(_RGB(0x6C, 0x6C, 0xFC), _RGB(0x6C, 0x6C, 0xFC)),
|
||||
/* 0b10011110 */ _PIXELS(RGB_WHITE, RGB_WHITE),
|
||||
/* 0b10011111 */ _PIXELS(RGB_WHITE, RGB_WHITE),
|
||||
/* 0b10100000 */ _PIXELS(RGB_BLACK, RGB_BLACK),
|
||||
/* 0b10100001 */ _PIXELS(RGB_BLACK, RGB_BLACK),
|
||||
/* 0b10100010 */ _PIXELS(_RGB(0x48, 0x48, 0x24), _RGB(0x24, 0x24, 0x00)),
|
||||
/* 0b10100011 */ _PIXELS(_RGB(0x48, 0x48, 0x24), _RGB(0xB4, 0x48, 0x00)),
|
||||
/* 0b10100100 */ _PIXELS(_RGB(0x24, 0x6C, 0x24), RGB_DGREEN),
|
||||
/* 0b10100101 */ _PIXELS(_RGB(0x24, 0x6C, 0x24), _RGB(0x24, 0x48, 0x48)),
|
||||
/* 0b10100110 */ _PIXELS(_RGB(0x24, 0xD8, 0x48), _RGB(0x00, 0xD8, 0x24)),
|
||||
/* 0b10100111 */ _PIXELS(_RGB(0x24, 0xD8, 0x48), _RGB(0x90, 0xD8, 0x00)),
|
||||
/* 0b10101000 */ _PIXELS(_RGB(0x24, 0x24, 0xB4), RGB_DBLUE),
|
||||
/* 0b10101001 */ _PIXELS(_RGB(0x24, 0x24, 0xB4), _RGB(0x90, 0x24, 0xD8)),
|
||||
/* 0b10101010 */ _PIXELS(_RGB(0x90, 0x90, 0x90), _RGB(0x90, 0x90, 0x90)),
|
||||
/* 0b10101011 */ _PIXELS(_RGB(0x90, 0x90, 0x90), _RGB(0xD8, 0x6C, 0xD8)),
|
||||
/* 0b10101100 */ _PIXELS(_RGB(0x24, 0xB4, 0xD8), _RGB(0x00, 0x90, 0xFC)),
|
||||
/* 0b10101101 */ _PIXELS(_RGB(0x24, 0xB4, 0xD8), _RGB(0x48, 0x6C, 0xFC)),
|
||||
/* 0b10101110 */ _PIXELS(_RGB(0x90, 0xFC, 0xB4), _RGB(0x90, 0xFC, 0xB4)),
|
||||
/* 0b10101111 */ _PIXELS(_RGB(0x90, 0xFC, 0xB4), RGB_WHITE),
|
||||
/* 0b10110000 */ _PIXELS(_RGB(0x90, 0x24, 0x90), RGB_BLACK),
|
||||
/* 0b10110001 */ _PIXELS(_RGB(0x90, 0x24, 0x90), _RGB(0x6C, 0x00, 0x6C)),
|
||||
/* 0b10110010 */ _PIXELS(_RGB(0xFC, 0x48, 0x48), _RGB(0xFC, 0x48, 0x00)),
|
||||
/* 0b10110011 */ _PIXELS(_RGB(0xFC, 0x48, 0x48), _RGB(0xFC, 0x48, 0x00)),
|
||||
/* 0b10110100 */ _PIXELS(_RGB(0x6C, 0x6C, 0x6C), _RGB(0x48, 0x48, 0x48)),
|
||||
/* 0b10110101 */ _PIXELS(_RGB(0x6C, 0x6C, 0x6C), _RGB(0x48, 0x48, 0x48)),
|
||||
/* 0b10110110 */ _PIXELS(_RGB(0xD8, 0xD8, 0x48), _RGB(0xD8, 0xD8, 0x00)),
|
||||
/* 0b10110111 */ _PIXELS(_RGB(0xD8, 0xD8, 0x48), _RGB(0xD8, 0xD8, 0x00)),
|
||||
/* 0b10111000 */ _PIXELS(_RGB(0xB4, 0x48, 0xFC), _RGB(0xB4, 0x24, 0xFC)),
|
||||
/* 0b10111001 */ _PIXELS(_RGB(0xB4, 0x48, 0xFC), _RGB(0xB4, 0x24, 0xFC)),
|
||||
/* 0b10111010 */ _PIXELS(RGB_PINK, RGB_PINK),
|
||||
/* 0b10111011 */ _PIXELS(RGB_PINK, RGB_PINK),
|
||||
/* 0b10111100 */ _PIXELS(RGB_WHITE, RGB_WHITE),
|
||||
/* 0b10111101 */ _PIXELS(RGB_WHITE, RGB_WHITE),
|
||||
/* 0b10111110 */ _PIXELS(RGB_WHITE, RGB_WHITE),
|
||||
/* 0b10111111 */ _PIXELS(RGB_WHITE, RGB_WHITE),
|
||||
/* 0b11000000 */ _PIXELS(RGB_BLACK, RGB_BLACK),
|
||||
/* 0b11000001 */ _PIXELS(RGB_BLACK, RGB_BLACK),
|
||||
/* 0b11000010 */ _PIXELS(RGB_BLACK, RGB_BLACK),
|
||||
/* 0b11000011 */ _PIXELS(RGB_BLACK, RGB_BLACK),
|
||||
/* 0b11000100 */ _PIXELS(_RGB(0x00, 0x48, 0x48), RGB_DGREEN),
|
||||
/* 0b11000101 */ _PIXELS(_RGB(0x00, 0x48, 0x48), _RGB(0x24, 0x48, 0x24)),
|
||||
/* 0b11000110 */ _PIXELS(_RGB(0x00, 0xB4, 0x6C), _RGB(0x00, 0xD8, 0x24)),
|
||||
/* 0b11000111 */ _PIXELS(RGB_BLACK, RGB_BLACK), //_PIXELS(_RGB(0x00, 0xB4, 0x6C), _RGB(0x90, 0xD8, 0x00)),
|
||||
/* 0b11001000 */ _PIXELS(_RGB(0x00, 0x24, 0xB4), RGB_DBLUE),
|
||||
/* 0b11001001 */ _PIXELS(_RGB(0x00, 0x24, 0xB4), _RGB(0x90, 0x24, 0xFC)),
|
||||
/* 0b11001010 */ _PIXELS(_RGB(0x6C, 0x90, 0xB4), _RGB(0x90, 0x90, 0x90)),
|
||||
/* 0b11001011 */ _PIXELS(_RGB(0x6C, 0x90, 0xB4), _RGB(0xD8, 0x6C, 0xD8)),
|
||||
/* 0b11001100 */ _PIXELS(_RGB(0x00, 0x90, 0xFC), _RGB(0x00, 0x90, 0xFC)),
|
||||
/* 0b11001101 */ _PIXELS(_RGB(0x00, 0x90, 0xFC), _RGB(0x48, 0x6C, 0xFC)),
|
||||
/* 0b11001110 */ _PIXELS(_RGB(0x6C, 0xD8, 0xB4), _RGB(0x90, 0xFC, 0xB4)),
|
||||
/* 0b11001111 */ _PIXELS(_RGB(0x6C, 0xD8, 0xB4), RGB_WHITE),
|
||||
/* 0b11010000 */ _PIXELS(_RGB(0x6C, 0x24, 0x90), RGB_BLACK),
|
||||
/* 0b11010001 */ _PIXELS(_RGB(0x6C, 0x24, 0x90), _RGB(0x6C, 0x00, 0x6C)),
|
||||
/* 0b11010010 */ _PIXELS(_RGB(0xD8, 0x48, 0x48), _RGB(0xFC, 0x48, 0x00)),
|
||||
/* 0b11010011 */ _PIXELS(_RGB(0xD8, 0x48, 0x48), _RGB(0xFC, 0x48, 0x00)),
|
||||
/* 0b11010100 */ _PIXELS(_RGB(0x48, 0x48, 0x6C), _RGB(0x48, 0x48, 0x48)),
|
||||
/* 0b11010101 */ _PIXELS(_RGB(0x48, 0x48, 0x6C), _RGB(0x48, 0x48, 0x48)),
|
||||
/* 0b11010110 */ _PIXELS(_RGB(0xB4, 0xB4, 0x48), _RGB(0xD8, 0xD8, 0x00)),
|
||||
/* 0b11010111 */ _PIXELS(_RGB(0xB4, 0xB4, 0x48), _RGB(0xD8, 0xD8, 0x00)),
|
||||
/* 0b11011000 */ _PIXELS(_RGB(0x90, 0x48, 0xFC), _RGB(0xB4, 0x24, 0xFC)),
|
||||
/* 0b11011001 */ _PIXELS(_RGB(0x90, 0x48, 0xFC), _RGB(0xB4, 0x24, 0xFC)),
|
||||
/* 0b11011010 */ _PIXELS(_RGB(0xD8, 0x6C, 0xFC), RGB_PINK),
|
||||
/* 0b11011011 */ _PIXELS(_RGB(0xD8, 0x6C, 0xFC), RGB_PINK),
|
||||
/* 0b11011100 */ _PIXELS(_RGB(0x6C, 0x6C, 0xFC), _RGB(0x6C, 0x6C, 0xFC)),
|
||||
/* 0b11011101 */ _PIXELS(_RGB(0x6C, 0x6C, 0xFC), _RGB(0x6C, 0x6C, 0xFC)),
|
||||
/* 0b11011110 */ _PIXELS(RGB_WHITE, RGB_WHITE),
|
||||
/* 0b11011111 */ _PIXELS(RGB_WHITE, RGB_WHITE),
|
||||
/* 0b11100000 */ _PIXELS(RGB_BLACK, RGB_BLACK),
|
||||
/* 0b11100001 */ _PIXELS(RGB_BLACK, RGB_BLACK),
|
||||
/* 0b11100010 */ _PIXELS(_RGB(0x48, 0x6C, 0x24), _RGB(0x24, 0x24, 0x00)),
|
||||
/* 0b11100011 */ _PIXELS(RGB_BLACK, RGB_BLACK), //_PIXELS(_RGB(0x48, 0x6C, 0x24), _RGB(0xB4, 0x48, 0x00)),
|
||||
/* 0b11100100 */ _PIXELS(_RGB(0x24, 0x6C, 0x24), RGB_DGREEN),
|
||||
/* 0b11100101 */ _PIXELS(_RGB(0x24, 0x6C, 0x24), _RGB(0x24, 0x48, 0x48)),
|
||||
/* 0b11100110 */ _PIXELS(_RGB(0x24, 0xD8, 0x48), _RGB(0x00, 0xD8, 0x24)),
|
||||
/* 0b11100111 */ _PIXELS(RGB_BLACK, RGB_BLACK), //_PIXELS(_RGB(0x24, 0xD8, 0x48), _RGB(0x90, 0xD8, 0x00)),
|
||||
/* 0b11101000 */ _PIXELS(_RGB(0x24, 0x48, 0xB4), _RGB(0x00, 0x24, 0xB4)),
|
||||
/* 0b11101001 */ _PIXELS(_RGB(0x24, 0x48, 0xB4), _RGB(0x90, 0x24, 0xD8)),
|
||||
/* 0b11101010 */ _PIXELS(_RGB(0x90, 0xB4, 0x90), _RGB(0x90, 0x90, 0x90)),
|
||||
/* 0b11101011 */ _PIXELS(_RGB(0x90, 0xB4, 0x90), _RGB(0xD8, 0x6C, 0xD8)),
|
||||
/* 0b11101100 */ _PIXELS(_RGB(0x24, 0xB4, 0xD8), _RGB(0x00, 0x90, 0xFC)),
|
||||
/* 0b11101101 */ _PIXELS(_RGB(0x24, 0xB4, 0xD8), _RGB(0x48, 0x6C, 0xFC)),
|
||||
/* 0b11101110 */ _PIXELS(_RGB(0x90, 0xFC, 0xB4), _RGB(0x90, 0xFC, 0xB4)),
|
||||
/* 0b11101111 */ _PIXELS(_RGB(0x90, 0xFC, 0xB4), RGB_WHITE),
|
||||
/* 0b11110000 */ _PIXELS(RGB_WHITE, RGB_BLACK),
|
||||
/* 0b11110001 */ _PIXELS(RGB_WHITE, _RGB(0x6C, 0x00, 0x6C)),
|
||||
/* 0b11110010 */ _PIXELS(RGB_WHITE, _RGB(0xFC, 0x48, 0x00)),
|
||||
/* 0b11110011 */ _PIXELS(RGB_WHITE, _RGB(0xFC, 0x48, 0x00)),
|
||||
/* 0b11110100 */ _PIXELS(RGB_WHITE, _RGB(0x48, 0x48, 0x48)),
|
||||
/* 0b11110101 */ _PIXELS(RGB_WHITE, _RGB(0x48, 0x48, 0x48)),
|
||||
/* 0b11110110 */ _PIXELS(RGB_WHITE, _RGB(0xD8, 0xD8, 0x00)),
|
||||
/* 0b11110111 */ _PIXELS(RGB_WHITE, _RGB(0xD8, 0xD8, 0x00)),
|
||||
/* 0b11111000 */ _PIXELS(RGB_WHITE, RGB_WHITE),
|
||||
/* 0b11111001 */ _PIXELS(RGB_WHITE, RGB_WHITE),
|
||||
/* 0b11111010 */ _PIXELS(RGB_WHITE, RGB_WHITE),
|
||||
/* 0b11111011 */ _PIXELS(RGB_WHITE, RGB_WHITE),
|
||||
/* 0b11111100 */ _PIXELS(RGB_WHITE, RGB_WHITE),
|
||||
/* 0b11111101 */ _PIXELS(RGB_WHITE, RGB_WHITE),
|
||||
/* 0b11111110 */ _PIXELS(RGB_WHITE, RGB_WHITE),
|
||||
/* 0b11111111 */ _PIXELS(RGB_WHITE, RGB_WHITE),
|
||||
|
||||
// Odd byte pixels
|
||||
/* 0b00000000 */ _PIXELS(RGB_BLACK, RGB_BLACK),
|
||||
/* 0b00000001 */ _PIXELS(RGB_BLACK, RGB_BLACK),
|
||||
/* 0b00000010 */ _PIXELS(RGB_BLACK, RGB_BLACK),
|
||||
/* 0b00000011 */ _PIXELS(RGB_BLACK, RGB_BLACK),
|
||||
/* 0b00000100 */ _PIXELS(RGB_BLACK, RGB_BLACK),
|
||||
/* 0b00000101 */ _PIXELS(RGB_BLACK, RGB_BLACK),
|
||||
/* 0b00000110 */ _PIXELS(RGB_BLACK, RGB_BLACK),
|
||||
/* 0b00000111 */ _PIXELS(RGB_BLACK, RGB_BLACK),
|
||||
/* 0b00001000 */ _PIXELS(RGB_BLACK, _RGB(0x24, 0x24, 0x00)),
|
||||
/* 0b00001001 */ _PIXELS(RGB_BLACK, _RGB(0x00, 0xB4, 0x24)),
|
||||
/* 0b00001010 */ _PIXELS(RGB_BLACK, _RGB(0x90, 0x90, 0x90)),
|
||||
/* 0b00001011 */ _PIXELS(RGB_BLACK, _RGB(0x90, 0xD8, 0x90)),
|
||||
/* 0b00001100 */ _PIXELS(RGB_BLACK, _RGB(0xFC, 0x48, 0x00)),
|
||||
/* 0b00001101 */ _PIXELS(RGB_BLACK, _RGB(0xD8, 0xB4, 0x00)),
|
||||
/* 0b00001110 */ _PIXELS(RGB_BLACK, _RGB(0xFC, 0x6C, 0xD8)),
|
||||
/* 0b00001111 */ _PIXELS(RGB_BLACK, RGB_WHITE),
|
||||
/* 0b00010000 */ _PIXELS(RGB_DGREEN, RGB_BLACK),
|
||||
/* 0b00010001 */ _PIXELS(RGB_DGREEN, RGB_DGREEN),
|
||||
/* 0b00010010 */ _PIXELS(_RGB(0x00, 0x6C, 0xB4), _RGB(0x00, 0x90, 0xD8)),
|
||||
/* 0b00010011 */ _PIXELS(_RGB(0x00, 0x6C, 0xB4), _RGB(0x00, 0x90, 0xD8)),
|
||||
/* 0b00010100 */ _PIXELS(_RGB(0x48, 0x48, 0x48), _RGB(0x48, 0x48, 0x48)),
|
||||
/* 0b00010101 */ _PIXELS(_RGB(0x48, 0x48, 0x48), _RGB(0x48, 0x48, 0x48)),
|
||||
/* 0b00010110 */ _PIXELS(_RGB(0x6C, 0x6C, 0xB4), _RGB(0x6C, 0x6C, 0xFC)),
|
||||
/* 0b00010111 */ _PIXELS(_RGB(0x6C, 0x6C, 0xB4), _RGB(0x6C, 0x6C, 0xFC)),
|
||||
/* 0b00011000 */ _PIXELS(_RGB(0x00, 0xD8, 0x24), _RGB(0x00, 0xD8, 0x24)),
|
||||
/* 0b00011001 */ _PIXELS(_RGB(0x00, 0xD8, 0x24), _RGB(0x00, 0xD8, 0x24)),
|
||||
/* 0b00011010 */ _PIXELS(_RGB(0x6C, 0x90, 0xFC), _RGB(0x90, 0xFC, 0xB4)),
|
||||
/* 0b00011011 */ _PIXELS(_RGB(0x6C, 0x90, 0xFC), _RGB(0x90, 0xFC, 0xB4)),
|
||||
/* 0b00011100 */ _PIXELS(_RGB(0xB4, 0xD8, 0x00), _RGB(0xD8, 0xD8, 0x00)),
|
||||
/* 0b00011101 */ _PIXELS(_RGB(0xB4, 0xD8, 0x00), _RGB(0xD8, 0xD8, 0x00)),
|
||||
/* 0b00011110 */ _PIXELS(RGB_WHITE, RGB_WHITE),
|
||||
/* 0b00011111 */ _PIXELS(RGB_WHITE, RGB_WHITE),
|
||||
/* 0b00100000 */ _PIXELS(RGB_BLACK, RGB_BLACK),
|
||||
/* 0b00100001 */ _PIXELS(RGB_BLACK, RGB_BLACK),
|
||||
/* 0b00100010 */ _PIXELS(RGB_DBLUE, RGB_DBLUE),
|
||||
/* 0b00100011 */ _PIXELS(RGB_DBLUE, _RGB(0x00, 0x6C, 0xD8)),
|
||||
/* 0b00100100 */ _PIXELS(_RGB(0xB4, 0x24, 0xFC), _RGB(0xB4, 0x24, 0xFC)),
|
||||
/* 0b00100101 */ _PIXELS(_RGB(0xB4, 0x24, 0xFC), _RGB(0x6C, 0x48, 0xFC)),
|
||||
/* 0b00100110 */ _PIXELS(_RGB(0xB4, 0x24, 0xFC), _RGB(0xB4, 0x24, 0xFC)),
|
||||
/* 0b00100111 */ _PIXELS(_RGB(0xB4, 0x24, 0xFC), _RGB(0x6C, 0x48, 0xFC)),
|
||||
/* 0b00101000 */ _PIXELS(_RGB(0x90, 0x90, 0x90), _RGB(0x90, 0x90, 0x90)),
|
||||
/* 0b00101001 */ _PIXELS(_RGB(0x90, 0x90, 0x90), _RGB(0x90, 0xD8, 0xB4)),
|
||||
/* 0b00101010 */ _PIXELS(_RGB(0x90, 0x90, 0x90), _RGB(0x90, 0x90, 0x90)),
|
||||
/* 0b00101011 */ _PIXELS(_RGB(0x90, 0x90, 0x90), _RGB(0x90, 0xD8, 0xB4)),
|
||||
/* 0b00101100 */ _PIXELS(RGB_PINK, RGB_PINK),
|
||||
/* 0b00101101 */ _PIXELS(RGB_PINK, _RGB(0xFC, 0xD8, 0xFC)),
|
||||
/* 0b00101110 */ _PIXELS(RGB_PINK, RGB_PINK),
|
||||
/* 0b00101111 */ _PIXELS(RGB_PINK, RGB_WHITE),
|
||||
/* 0b00110000 */ _PIXELS(_RGB(0x00, 0x90, 0xFC), RGB_BLACK),
|
||||
/* 0b00110001 */ _PIXELS(_RGB(0x00, 0x90, 0xFC), _RGB(0x00, 0x90, 0xFC)),
|
||||
/* 0b00110010 */ _PIXELS(_RGB(0x00, 0x90, 0xFC), _RGB(0x00, 0x90, 0xFC)),
|
||||
/* 0b00110011 */ _PIXELS(_RGB(0x00, 0x90, 0xFC), _RGB(0x00, 0x90, 0xFC)),
|
||||
/* 0b00110100 */ _PIXELS(_RGB(0x6C, 0x6C, 0xFC), _RGB(0x6C, 0x6C, 0xFC)),
|
||||
/* 0b00110101 */ _PIXELS(_RGB(0x6C, 0x6C, 0xFC), _RGB(0x6C, 0x6C, 0xFC)),
|
||||
/* 0b00110110 */ _PIXELS(_RGB(0x6C, 0x6C, 0xFC), _RGB(0x6C, 0x6C, 0xFC)),
|
||||
/* 0b00110111 */ _PIXELS(_RGB(0x6C, 0x6C, 0xFC), _RGB(0x6C, 0x6C, 0xFC)),
|
||||
/* 0b00111000 */ _PIXELS(_RGB(0x90, 0xFC, 0xB4), _RGB(0x90, 0xFC, 0xB4)),
|
||||
/* 0b00111001 */ _PIXELS(_RGB(0x90, 0xFC, 0xB4), _RGB(0x90, 0xFC, 0xB4)),
|
||||
/* 0b00111010 */ _PIXELS(_RGB(0x90, 0xFC, 0xB4), _RGB(0x90, 0xFC, 0xB4)),
|
||||
/* 0b00111011 */ _PIXELS(_RGB(0x90, 0xFC, 0xB4), _RGB(0x90, 0xFC, 0xB4)),
|
||||
/* 0b00111100 */ _PIXELS(RGB_WHITE, RGB_WHITE),
|
||||
/* 0b00111101 */ _PIXELS(RGB_WHITE, RGB_WHITE),
|
||||
/* 0b00111110 */ _PIXELS(RGB_WHITE, RGB_WHITE),
|
||||
/* 0b00111111 */ _PIXELS(RGB_WHITE, RGB_WHITE),
|
||||
/* 0b01000000 */ _PIXELS(RGB_BLACK, RGB_BLACK),
|
||||
/* 0b01000001 */ _PIXELS(RGB_BLACK, RGB_BLACK),
|
||||
/* 0b01000010 */ _PIXELS(RGB_BLACK, RGB_BLACK),
|
||||
/* 0b01000011 */ _PIXELS(RGB_BLACK, RGB_BLACK),
|
||||
/* 0b01000100 */ _PIXELS(_RGB(0x6C, 0x00, 0x6C), _RGB(0x6C, 0x00, 0x6C)),
|
||||
/* 0b01000101 */ _PIXELS(_RGB(0x6C, 0x00, 0x6C), _RGB(0x48, 0x24, 0x48)),
|
||||
/* 0b01000110 */ _PIXELS(_RGB(0x90, 0x24, 0xD8), _RGB(0xB4, 0x24, 0xFC)),
|
||||
/* 0b01000111 */ _PIXELS(_RGB(0x90, 0x24, 0xD8), _RGB(0x6C, 0x48, 0xFC)),
|
||||
/* 0b01001000 */ _PIXELS(_RGB(0xFC, 0x48, 0x00), _RGB(0xFC, 0x48, 0x00)),
|
||||
/* 0b01001001 */ _PIXELS(_RGB(0xFC, 0x48, 0x00), _RGB(0xD8, 0xB4, 0x00)),
|
||||
/* 0b01001010 */ _PIXELS(_RGB(0xFC, 0x6C, 0xB4), _RGB(0xFC, 0x6C, 0xD8)),
|
||||
/* 0b01001011 */ _PIXELS(_RGB(0xFC, 0x6C, 0xB4), _RGB(0xFC, 0xD8, 0xD8)),
|
||||
/* 0b01001100 */ _PIXELS(_RGB(0xFC, 0x48, 0x00), _RGB(0xFC, 0x48, 0x00)),
|
||||
/* 0b01001101 */ _PIXELS(_RGB(0xFC, 0x48, 0x00), _RGB(0xD8, 0xB4, 0x00)),
|
||||
/* 0b01001110 */ _PIXELS(_RGB(0xFC, 0x6C, 0xB4), _RGB(0xFC, 0x6C, 0xD8)),
|
||||
/* 0b01001111 */ _PIXELS(_RGB(0xFC, 0x6C, 0xB4), RGB_WHITE),
|
||||
/* 0b01010000 */ _PIXELS(_RGB(0x48, 0x48, 0x48), RGB_BLACK),
|
||||
/* 0b01010001 */ _PIXELS(_RGB(0x48, 0x48, 0x48), _RGB(0x48, 0x48, 0x48)),
|
||||
/* 0b01010010 */ _PIXELS(_RGB(0x6C, 0x6C, 0xD8), _RGB(0x6C, 0x6C, 0xFC)),
|
||||
/* 0b01010011 */ _PIXELS(_RGB(0x6C, 0x6C, 0xD8), _RGB(0x6C, 0x6C, 0xFC)),
|
||||
/* 0b01010100 */ _PIXELS(_RGB(0x48, 0x48, 0x48), _RGB(0x48, 0x48, 0x48)),
|
||||
/* 0b01010101 */ _PIXELS(_RGB(0x48, 0x48, 0x48), _RGB(0x48, 0x48, 0x48)),
|
||||
/* 0b01010110 */ _PIXELS(_RGB(0x6C, 0x6C, 0xD8), _RGB(0x6C, 0x6C, 0xFC)),
|
||||
/* 0b01010111 */ _PIXELS(_RGB(0x6C, 0x6C, 0xD8), _RGB(0x6C, 0x6C, 0xFC)),
|
||||
/* 0b01011000 */ _PIXELS(_RGB(0xD8, 0xD8, 0x00), _RGB(0xD8, 0xD8, 0x00)),
|
||||
/* 0b01011001 */ _PIXELS(_RGB(0xD8, 0xD8, 0x00), _RGB(0xD8, 0xD8, 0x00)),
|
||||
/* 0b01011010 */ _PIXELS(_RGB(0xFC, 0xFC, 0xB4), _RGB(0xFC, 0xFC, 0xD8)),
|
||||
/* 0b01011011 */ _PIXELS(_RGB(0xFC, 0xFC, 0xB4), _RGB(0xFC, 0xFC, 0xD8)),
|
||||
/* 0b01011100 */ _PIXELS(_RGB(0xD8, 0xD8, 0x00), _RGB(0xD8, 0xD8, 0x00)),
|
||||
/* 0b01011101 */ _PIXELS(_RGB(0xD8, 0xD8, 0x00), _RGB(0xD8, 0xD8, 0x00)),
|
||||
/* 0b01011110 */ _PIXELS(RGB_WHITE, RGB_WHITE),
|
||||
/* 0b01011111 */ _PIXELS(RGB_WHITE, RGB_WHITE),
|
||||
/* 0b01100000 */ _PIXELS(RGB_BLACK, RGB_BLACK),
|
||||
/* 0b01100001 */ _PIXELS(RGB_BLACK, RGB_BLACK),
|
||||
/* 0b01100010 */ _PIXELS(_RGB(0xB4, 0x24, 0xFC), _RGB(0xB4, 0x24, 0xFC)),
|
||||
/* 0b01100011 */ _PIXELS(_RGB(0xB4, 0x24, 0xFC), _RGB(0x6C, 0x48, 0xFC)),
|
||||
/* 0b01100100 */ _PIXELS(_RGB(0xB4, 0x24, 0xFC), _RGB(0xB4, 0x24, 0xFC)),
|
||||
/* 0b01100101 */ _PIXELS(_RGB(0xB4, 0x24, 0xFC), _RGB(0x6C, 0x48, 0xFC)),
|
||||
/* 0b01100110 */ _PIXELS(_RGB(0xB4, 0x24, 0xFC), _RGB(0xB4, 0x24, 0xFC)),
|
||||
/* 0b01100111 */ _PIXELS(_RGB(0xB4, 0x24, 0xFC), _RGB(0x6C, 0x48, 0xFC)),
|
||||
/* 0b01101000 */ _PIXELS(RGB_PINK, RGB_PINK),
|
||||
/* 0b01101001 */ _PIXELS(RGB_PINK, _RGB(0xFC, 0xD8, 0xFC)),
|
||||
/* 0b01101010 */ _PIXELS(RGB_PINK, RGB_PINK),
|
||||
/* 0b01101011 */ _PIXELS(RGB_PINK, _RGB(0xFC, 0xD8, 0xFC)),
|
||||
/* 0b01101100 */ _PIXELS(RGB_PINK, RGB_PINK),
|
||||
/* 0b01101101 */ _PIXELS(RGB_PINK, _RGB(0xFC, 0xD8, 0xFC)),
|
||||
/* 0b01101110 */ _PIXELS(RGB_PINK, RGB_PINK),
|
||||
/* 0b01101111 */ _PIXELS(RGB_PINK, RGB_WHITE),
|
||||
/* 0b01110000 */ _PIXELS(_RGB(0x6C, 0x6C, 0xFC), RGB_BLACK),
|
||||
/* 0b01110001 */ _PIXELS(_RGB(0x6C, 0x6C, 0xFC), _RGB(0x6C, 0x6C, 0xFC)),
|
||||
/* 0b01110010 */ _PIXELS(_RGB(0x6C, 0x6C, 0xFC), _RGB(0x6C, 0x6C, 0xFC)),
|
||||
/* 0b01110011 */ _PIXELS(_RGB(0x6C, 0x6C, 0xFC), _RGB(0x6C, 0x6C, 0xFC)),
|
||||
/* 0b01110100 */ _PIXELS(_RGB(0x6C, 0x6C, 0xFC), _RGB(0x6C, 0x6C, 0xFC)),
|
||||
/* 0b01110101 */ _PIXELS(_RGB(0x6C, 0x6C, 0xFC), _RGB(0x6C, 0x6C, 0xFC)),
|
||||
/* 0b01110110 */ _PIXELS(_RGB(0x6C, 0x6C, 0xFC), _RGB(0x6C, 0x6C, 0xFC)),
|
||||
/* 0b01110111 */ _PIXELS(_RGB(0x6C, 0x6C, 0xFC), _RGB(0x6C, 0x6C, 0xFC)),
|
||||
/* 0b01111000 */ _PIXELS(RGB_WHITE, RGB_WHITE),
|
||||
/* 0b01111001 */ _PIXELS(RGB_WHITE, RGB_WHITE),
|
||||
/* 0b01111010 */ _PIXELS(RGB_WHITE, RGB_WHITE),
|
||||
/* 0b01111011 */ _PIXELS(RGB_WHITE, RGB_WHITE),
|
||||
/* 0b01111100 */ _PIXELS(RGB_WHITE, RGB_WHITE),
|
||||
/* 0b01111101 */ _PIXELS(RGB_WHITE, RGB_WHITE),
|
||||
/* 0b01111110 */ _PIXELS(RGB_WHITE, RGB_WHITE),
|
||||
/* 0b01111111 */ _PIXELS(RGB_WHITE, RGB_WHITE),
|
||||
/* 0b10000000 */ _PIXELS(RGB_BLACK, RGB_BLACK),
|
||||
/* 0b10000001 */ _PIXELS(RGB_BLACK, RGB_BLACK),
|
||||
/* 0b10000010 */ _PIXELS(RGB_BLACK, RGB_BLACK),
|
||||
/* 0b10000011 */ _PIXELS(RGB_BLACK, RGB_BLACK),
|
||||
/* 0b10000100 */ _PIXELS(RGB_BLACK, RGB_BLACK),
|
||||
/* 0b10000101 */ _PIXELS(RGB_BLACK, RGB_BLACK),
|
||||
/* 0b10000110 */ _PIXELS(RGB_BLACK, RGB_BLACK),
|
||||
/* 0b10000111 */ _PIXELS(RGB_BLACK, RGB_BLACK),
|
||||
/* 0b10001000 */ _PIXELS(_RGB(0x24, 0x24, 0x00), _RGB(0x24, 0x24, 0x00)),
|
||||
/* 0b10001001 */ _PIXELS(_RGB(0x24, 0x24, 0x00), _RGB(0x00, 0xB4, 0x24)),
|
||||
/* 0b10001010 */ _PIXELS(_RGB(0x6C, 0x6C, 0x6C), _RGB(0x90, 0x90, 0x90)),
|
||||
/* 0b10001011 */ _PIXELS(_RGB(0x6C, 0x6C, 0x6C), _RGB(0x90, 0xD8, 0x90)),
|
||||
/* 0b10001100 */ _PIXELS(_RGB(0xD8, 0x48, 0x00), _RGB(0xFC, 0x48, 0x00)),
|
||||
/* 0b10001101 */ _PIXELS(_RGB(0xD8, 0x48, 0x00), _RGB(0xD8, 0xB4, 0x00)),
|
||||
/* 0b10001110 */ _PIXELS(_RGB(0xD8, 0x6C, 0xB4), _RGB(0xFC, 0x6C, 0xD8)),
|
||||
/* 0b10001111 */ _PIXELS(_RGB(0xD8, 0x6C, 0xB4), RGB_WHITE),
|
||||
/* 0b10010000 */ _PIXELS(RGB_DGREEN, RGB_BLACK),
|
||||
/* 0b10010001 */ _PIXELS(RGB_DGREEN, RGB_DGREEN),
|
||||
/* 0b10010010 */ _PIXELS(_RGB(0x00, 0x6C, 0xB4), _RGB(0x00, 0x90, 0xD8)),
|
||||
/* 0b10010011 */ _PIXELS(_RGB(0x00, 0x6C, 0xB4), _RGB(0x00, 0x90, 0xD8)),
|
||||
/* 0b10010100 */ _PIXELS(_RGB(0x48, 0x48, 0x48), _RGB(0x48, 0x48, 0x48)),
|
||||
/* 0b10010101 */ _PIXELS(_RGB(0x48, 0x48, 0x48), _RGB(0x48, 0x48, 0x48)),
|
||||
/* 0b10010110 */ _PIXELS(_RGB(0x6C, 0x6C, 0xB4), _RGB(0x6C, 0x6C, 0xFC)),
|
||||
/* 0b10010111 */ _PIXELS(_RGB(0x6C, 0x6C, 0xB4), _RGB(0x6C, 0x6C, 0xFC)),
|
||||
/* 0b10011000 */ _PIXELS(_RGB(0x00, 0xD8, 0x24), _RGB(0x00, 0xD8, 0x24)),
|
||||
/* 0b10011001 */ _PIXELS(_RGB(0x00, 0xD8, 0x24), _RGB(0x00, 0xD8, 0x24)),
|
||||
/* 0b10011010 */ _PIXELS(_RGB(0x6C, 0x90, 0xFC), _RGB(0x90, 0xFC, 0xB4)),
|
||||
/* 0b10011011 */ _PIXELS(_RGB(0x6C, 0x90, 0xFC), _RGB(0x90, 0xFC, 0xB4)),
|
||||
/* 0b10011100 */ _PIXELS(_RGB(0xB4, 0xD8, 0x00), _RGB(0xD8, 0xD8, 0x00)),
|
||||
/* 0b10011101 */ _PIXELS(_RGB(0xB4, 0xD8, 0x00), _RGB(0xD8, 0xD8, 0x00)),
|
||||
/* 0b10011110 */ _PIXELS(RGB_WHITE, RGB_WHITE),
|
||||
/* 0b10011111 */ _PIXELS(RGB_WHITE, RGB_WHITE),
|
||||
/* 0b10100000 */ _PIXELS(RGB_BLACK, RGB_BLACK),
|
||||
/* 0b10100001 */ _PIXELS(RGB_BLACK, RGB_BLACK),
|
||||
/* 0b10100010 */ _PIXELS(RGB_DBLUE, RGB_DBLUE),
|
||||
/* 0b10100011 */ _PIXELS(RGB_DBLUE, _RGB(0x00, 0x6C, 0xD8)),
|
||||
/* 0b10100100 */ _PIXELS(_RGB(0xB4, 0x24, 0xFC), _RGB(0xB4, 0x24, 0xFC)),
|
||||
/* 0b10100101 */ _PIXELS(_RGB(0xB4, 0x24, 0xFC), _RGB(0x6C, 0x48, 0xFC)),
|
||||
/* 0b10100110 */ _PIXELS(_RGB(0xB4, 0x24, 0xFC), _RGB(0xB4, 0x24, 0xFC)),
|
||||
/* 0b10100111 */ _PIXELS(_RGB(0xB4, 0x24, 0xFC), _RGB(0x6C, 0x48, 0xFC)),
|
||||
/* 0b10101000 */ _PIXELS(_RGB(0x90, 0x90, 0x90), _RGB(0x90, 0x90, 0x90)),
|
||||
/* 0b10101001 */ _PIXELS(_RGB(0x90, 0x90, 0x90), _RGB(0x90, 0xD8, 0xB4)),
|
||||
/* 0b10101010 */ _PIXELS(_RGB(0x90, 0x90, 0x90), _RGB(0x90, 0x90, 0x90)),
|
||||
/* 0b10101011 */ _PIXELS(_RGB(0x90, 0x90, 0x90), _RGB(0x90, 0xD8, 0xB4)),
|
||||
/* 0b10101100 */ _PIXELS(RGB_PINK, RGB_PINK),
|
||||
/* 0b10101101 */ _PIXELS(RGB_PINK, _RGB(0xFC, 0xD8, 0xFC)),
|
||||
/* 0b10101110 */ _PIXELS(RGB_PINK, RGB_PINK),
|
||||
/* 0b10101111 */ _PIXELS(RGB_PINK, RGB_WHITE),
|
||||
/* 0b10110000 */ _PIXELS(_RGB(0x00, 0x90, 0xFC), RGB_BLACK),
|
||||
/* 0b10110001 */ _PIXELS(_RGB(0x00, 0x90, 0xFC), _RGB(0x00, 0x90, 0xFC)),
|
||||
/* 0b10110010 */ _PIXELS(_RGB(0x00, 0x90, 0xFC), _RGB(0x00, 0x90, 0xFC)),
|
||||
/* 0b10110011 */ _PIXELS(_RGB(0x00, 0x90, 0xFC), _RGB(0x00, 0x90, 0xFC)),
|
||||
/* 0b10110100 */ _PIXELS(_RGB(0x6C, 0x6C, 0xFC), _RGB(0x6C, 0x6C, 0xFC)),
|
||||
/* 0b10110101 */ _PIXELS(_RGB(0x6C, 0x6C, 0xFC), _RGB(0x6C, 0x6C, 0xFC)),
|
||||
/* 0b10110110 */ _PIXELS(_RGB(0x6C, 0x6C, 0xFC), _RGB(0x6C, 0x6C, 0xFC)),
|
||||
/* 0b10110111 */ _PIXELS(_RGB(0x6C, 0x6C, 0xFC), _RGB(0x6C, 0x6C, 0xFC)),
|
||||
/* 0b10111000 */ _PIXELS(_RGB(0x90, 0xFC, 0xB4), _RGB(0x90, 0xFC, 0xB4)),
|
||||
/* 0b10111001 */ _PIXELS(_RGB(0x90, 0xFC, 0xB4), _RGB(0x90, 0xFC, 0xB4)),
|
||||
/* 0b10111010 */ _PIXELS(_RGB(0x90, 0xFC, 0xB4), _RGB(0x90, 0xFC, 0xB4)),
|
||||
/* 0b10111011 */ _PIXELS(_RGB(0x90, 0xFC, 0xB4), _RGB(0x90, 0xFC, 0xB4)),
|
||||
/* 0b10111100 */ _PIXELS(RGB_WHITE, RGB_WHITE),
|
||||
/* 0b10111101 */ _PIXELS(RGB_WHITE, RGB_WHITE),
|
||||
/* 0b10111110 */ _PIXELS(RGB_WHITE, RGB_WHITE),
|
||||
/* 0b10111111 */ _PIXELS(RGB_WHITE, RGB_WHITE),
|
||||
/* 0b11000000 */ _PIXELS(RGB_BLACK, RGB_BLACK),
|
||||
/* 0b11000001 */ _PIXELS(RGB_BLACK, RGB_BLACK),
|
||||
/* 0b11000010 */ _PIXELS(RGB_BLACK, RGB_BLACK),
|
||||
/* 0b11000011 */ _PIXELS(RGB_BLACK, RGB_BLACK),
|
||||
/* 0b11000100 */ _PIXELS(_RGB(0x6C, 0x00, 0x6C), _RGB(0x6C, 0x00, 0x6C)),
|
||||
/* 0b11000101 */ _PIXELS(_RGB(0x6C, 0x00, 0x6C), _RGB(0x48, 0x24, 0x48)),
|
||||
/* 0b11000110 */ _PIXELS(_RGB(0x90, 0x24, 0xD8), _RGB(0xB4, 0x24, 0xFC)),
|
||||
/* 0b11000111 */ _PIXELS(RGB_BLACK, RGB_BLACK), //_PIXELS(_RGB(0x90, 0x24, 0xD8), _RGB(0x6C, 0x48, 0xFC)),
|
||||
/* 0b11001000 */ _PIXELS(_RGB(0xFC, 0x48, 0x00), _RGB(0xFC, 0x48, 0x00)),
|
||||
/* 0b11001001 */ _PIXELS(_RGB(0xFC, 0x48, 0x00), _RGB(0xD8, 0xB4, 0x00)),
|
||||
/* 0b11001010 */ _PIXELS(_RGB(0xFC, 0x6C, 0xB4), _RGB(0xFC, 0x6C, 0xD8)),
|
||||
/* 0b11001011 */ _PIXELS(_RGB(0xFC, 0x6C, 0xB4), _RGB(0xFC, 0xD8, 0xD8)),
|
||||
/* 0b11001100 */ _PIXELS(_RGB(0xFC, 0x48, 0x00), _RGB(0xFC, 0x48, 0x00)),
|
||||
/* 0b11001101 */ _PIXELS(_RGB(0xFC, 0x48, 0x00), _RGB(0xD8, 0xB4, 0x00)),
|
||||
/* 0b11001110 */ _PIXELS(_RGB(0xFC, 0x6C, 0xB4), _RGB(0xFC, 0x6C, 0xD8)),
|
||||
/* 0b11001111 */ _PIXELS(_RGB(0xFC, 0x6C, 0xB4), RGB_WHITE),
|
||||
/* 0b11010000 */ _PIXELS(_RGB(0x48, 0x48, 0x48), RGB_BLACK),
|
||||
/* 0b11010001 */ _PIXELS(_RGB(0x48, 0x48, 0x48), _RGB(0x48, 0x48, 0x48)),
|
||||
/* 0b11010010 */ _PIXELS(_RGB(0x6C, 0x6C, 0xD8), _RGB(0x6C, 0x6C, 0xFC)),
|
||||
/* 0b11010011 */ _PIXELS(_RGB(0x6C, 0x6C, 0xD8), _RGB(0x6C, 0x6C, 0xFC)),
|
||||
/* 0b11010100 */ _PIXELS(_RGB(0x48, 0x48, 0x48), _RGB(0x48, 0x48, 0x48)),
|
||||
/* 0b11010101 */ _PIXELS(_RGB(0x48, 0x48, 0x48), _RGB(0x48, 0x48, 0x48)),
|
||||
/* 0b11010110 */ _PIXELS(_RGB(0x6C, 0x6C, 0xD8), _RGB(0x6C, 0x6C, 0xFC)),
|
||||
/* 0b11010111 */ _PIXELS(_RGB(0x6C, 0x6C, 0xD8), _RGB(0x6C, 0x6C, 0xFC)),
|
||||
/* 0b11011000 */ _PIXELS(_RGB(0xD8, 0xD8, 0x00), _RGB(0xD8, 0xD8, 0x00)),
|
||||
/* 0b11011001 */ _PIXELS(_RGB(0xD8, 0xD8, 0x00), _RGB(0xD8, 0xD8, 0x00)),
|
||||
/* 0b11011010 */ _PIXELS(_RGB(0xFC, 0xFC, 0xB4), _RGB(0xFC, 0xFC, 0xD8)),
|
||||
/* 0b11011011 */ _PIXELS(_RGB(0xFC, 0xFC, 0xB4), _RGB(0xFC, 0xFC, 0xD8)),
|
||||
/* 0b11011100 */ _PIXELS(_RGB(0xD8, 0xD8, 0x00), _RGB(0xD8, 0xD8, 0x00)),
|
||||
/* 0b11011101 */ _PIXELS(_RGB(0xD8, 0xD8, 0x00), _RGB(0xD8, 0xD8, 0x00)),
|
||||
/* 0b11011110 */ _PIXELS(RGB_WHITE, RGB_WHITE),
|
||||
/* 0b11011111 */ _PIXELS(RGB_WHITE, RGB_WHITE),
|
||||
/* 0b11100000 */ _PIXELS(RGB_BLACK, RGB_BLACK),
|
||||
/* 0b11100001 */ _PIXELS(RGB_BLACK, RGB_BLACK),
|
||||
/* 0b11100010 */ _PIXELS(_RGB(0xB4, 0x24, 0xFC), _RGB(0xB4, 0x24, 0xFC)),
|
||||
/* 0b11100011 */ _PIXELS(RGB_BLACK, RGB_BLACK), //_PIXELS(_RGB(0xB4, 0x24, 0xFC), _RGB(0x6C, 0x48, 0xFC)),
|
||||
/* 0b11100100 */ _PIXELS(_RGB(0xB4, 0x24, 0xFC), _RGB(0xB4, 0x24, 0xFC)),
|
||||
/* 0b11100101 */ _PIXELS(_RGB(0xB4, 0x24, 0xFC), _RGB(0x6C, 0x48, 0xFC)),
|
||||
/* 0b11100110 */ _PIXELS(_RGB(0xB4, 0x24, 0xFC), _RGB(0xB4, 0x24, 0xFC)),
|
||||
/* 0b11100111 */ _PIXELS(RGB_BLACK, RGB_BLACK), //_PIXELS(_RGB(0xB4, 0x24, 0xFC), _RGB(0x6C, 0x48, 0xFC)),
|
||||
/* 0b11101000 */ _PIXELS(RGB_PINK, RGB_PINK),
|
||||
/* 0b11101001 */ _PIXELS(RGB_PINK, _RGB(0xFC, 0xD8, 0xFC)),
|
||||
/* 0b11101010 */ _PIXELS(RGB_PINK, RGB_PINK),
|
||||
/* 0b11101011 */ _PIXELS(RGB_PINK, _RGB(0xFC, 0xD8, 0xFC)),
|
||||
/* 0b11101100 */ _PIXELS(RGB_PINK, RGB_PINK),
|
||||
/* 0b11101101 */ _PIXELS(RGB_PINK, _RGB(0xFC, 0xD8, 0xFC)),
|
||||
/* 0b11101110 */ _PIXELS(RGB_PINK, RGB_PINK),
|
||||
/* 0b11101111 */ _PIXELS(RGB_PINK, RGB_WHITE),
|
||||
/* 0b11110000 */ _PIXELS(RGB_WHITE, RGB_BLACK),
|
||||
/* 0b11110001 */ _PIXELS(RGB_WHITE, _RGB(0x6C, 0x6C, 0xFC)),
|
||||
/* 0b11110010 */ _PIXELS(RGB_WHITE, _RGB(0x6C, 0x6C, 0xFC)),
|
||||
/* 0b11110011 */ _PIXELS(RGB_WHITE, _RGB(0x6C, 0x6C, 0xFC)),
|
||||
/* 0b11110100 */ _PIXELS(RGB_WHITE, _RGB(0x6C, 0x6C, 0xFC)),
|
||||
/* 0b11110101 */ _PIXELS(RGB_WHITE, _RGB(0x6C, 0x6C, 0xFC)),
|
||||
/* 0b11110110 */ _PIXELS(RGB_WHITE, _RGB(0x6C, 0x6C, 0xFC)),
|
||||
/* 0b11110111 */ _PIXELS(RGB_WHITE, _RGB(0x6C, 0x6C, 0xFC)),
|
||||
/* 0b11111000 */ _PIXELS(RGB_WHITE, RGB_WHITE),
|
||||
/* 0b11111001 */ _PIXELS(RGB_WHITE, RGB_WHITE),
|
||||
/* 0b11111010 */ _PIXELS(RGB_WHITE, RGB_WHITE),
|
||||
/* 0b11111011 */ _PIXELS(RGB_WHITE, RGB_WHITE),
|
||||
/* 0b11111100 */ _PIXELS(RGB_WHITE, RGB_WHITE),
|
||||
/* 0b11111101 */ _PIXELS(RGB_WHITE, RGB_WHITE),
|
||||
/* 0b11111110 */ _PIXELS(RGB_WHITE, RGB_WHITE),
|
||||
/* 0b11111111 */ _PIXELS(RGB_WHITE, RGB_WHITE),
|
||||
};
|
||||
#undef _PIXELS
|
41
vga/hires_dot_patterns.h
Normal file
41
vga/hires_dot_patterns.h
Normal file
@ -0,0 +1,41 @@
|
||||
#pragma once
|
||||
|
||||
#include "common/config.h"
|
||||
#include <stdint.h>
|
||||
|
||||
// Mapping of a hires video byte to 14 half-pixel dots.
|
||||
// Bits are displayed from MSB to LSB.
|
||||
static uint16_t DELAYED_COPY_DATA(hires_dot_patterns)[256] = {
|
||||
0x0000,0x3000,0x0c00,0x3c00,0x0300,0x3300,0x0f00,0x3f00,
|
||||
0x00c0,0x30c0,0x0cc0,0x3cc0,0x03c0,0x33c0,0x0fc0,0x3fc0,
|
||||
0x0030,0x3030,0x0c30,0x3c30,0x0330,0x3330,0x0f30,0x3f30,
|
||||
0x00f0,0x30f0,0x0cf0,0x3cf0,0x03f0,0x33f0,0x0ff0,0x3ff0,
|
||||
0x000c,0x300c,0x0c0c,0x3c0c,0x030c,0x330c,0x0f0c,0x3f0c,
|
||||
0x00cc,0x30cc,0x0ccc,0x3ccc,0x03cc,0x33cc,0x0fcc,0x3fcc,
|
||||
0x003c,0x303c,0x0c3c,0x3c3c,0x033c,0x333c,0x0f3c,0x3f3c,
|
||||
0x00fc,0x30fc,0x0cfc,0x3cfc,0x03fc,0x33fc,0x0ffc,0x3ffc,
|
||||
0x0003,0x3003,0x0c03,0x3c03,0x0303,0x3303,0x0f03,0x3f03,
|
||||
0x00c3,0x30c3,0x0cc3,0x3cc3,0x03c3,0x33c3,0x0fc3,0x3fc3,
|
||||
0x0033,0x3033,0x0c33,0x3c33,0x0333,0x3333,0x0f33,0x3f33,
|
||||
0x00f3,0x30f3,0x0cf3,0x3cf3,0x03f3,0x33f3,0x0ff3,0x3ff3,
|
||||
0x000f,0x300f,0x0c0f,0x3c0f,0x030f,0x330f,0x0f0f,0x3f0f,
|
||||
0x00cf,0x30cf,0x0ccf,0x3ccf,0x03cf,0x33cf,0x0fcf,0x3fcf,
|
||||
0x003f,0x303f,0x0c3f,0x3c3f,0x033f,0x333f,0x0f3f,0x3f3f,
|
||||
0x00ff,0x30ff,0x0cff,0x3cff,0x03ff,0x33ff,0x0fff,0x3fff,
|
||||
0x0000,0x1800,0x0600,0x1e00,0x0180,0x1980,0x0780,0x1f80,
|
||||
0x0060,0x1860,0x0660,0x1e60,0x01e0,0x19e0,0x07e0,0x1fe0,
|
||||
0x0018,0x1818,0x0618,0x1e18,0x0198,0x1998,0x0798,0x1f98,
|
||||
0x0078,0x1878,0x0678,0x1e78,0x01f8,0x19f8,0x07f8,0x1ff8,
|
||||
0x0006,0x1806,0x0606,0x1e06,0x0186,0x1986,0x0786,0x1f86,
|
||||
0x0066,0x1866,0x0666,0x1e66,0x01e6,0x19e6,0x07e6,0x1fe6,
|
||||
0x001e,0x181e,0x061e,0x1e1e,0x019e,0x199e,0x079e,0x1f9e,
|
||||
0x007e,0x187e,0x067e,0x1e7e,0x01fe,0x19fe,0x07fe,0x1ffe,
|
||||
0x0001,0x1801,0x0601,0x1e01,0x0181,0x1981,0x0781,0x1f81,
|
||||
0x0061,0x1861,0x0661,0x1e61,0x01e1,0x19e1,0x07e1,0x1fe1,
|
||||
0x0019,0x1819,0x0619,0x1e19,0x0199,0x1999,0x0799,0x1f99,
|
||||
0x0079,0x1879,0x0679,0x1e79,0x01f9,0x19f9,0x07f9,0x1ff9,
|
||||
0x0007,0x1807,0x0607,0x1e07,0x0187,0x1987,0x0787,0x1f87,
|
||||
0x0067,0x1867,0x0667,0x1e67,0x01e7,0x19e7,0x07e7,0x1fe7,
|
||||
0x001f,0x181f,0x061f,0x1e1f,0x019f,0x199f,0x079f,0x1f9f,
|
||||
0x007f,0x187f,0x067f,0x1e7f,0x01ff,0x19ff,0x07ff,0x1fff,
|
||||
};
|
74
vga/logo.h
Normal file
74
vga/logo.h
Normal file
@ -0,0 +1,74 @@
|
||||
#pragma once
|
||||
|
||||
#include "common/config.h"
|
||||
|
||||
//uint8_t DELAYED_COPY_DATA(PicoPalLogo)[2112] = {
|
||||
|
||||
uint8_t __attribute__((section(".delayed_data."))) PicoPalLogo[2112] = {
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x50, 0x44, 0x44, 0x44, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x44, 0x44, 0x44, 0x05, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x50, 0x44, 0x44, 0x44, 0x44, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x44, 0x44, 0x44, 0x05, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x50, 0x44, 0x44, 0x44, 0x44, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x44, 0x44, 0x44, 0x05, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x50, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x05, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x50, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x05, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x50, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x05, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x50, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x05, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x50, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x05, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x50, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x05, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x50, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0xDD, 0xD4, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x4D, 0xDD, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x05, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x50, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0xDD, 0xD4, 0xF4, 0x44, 0xF4, 0x44, 0xFF, 0xF4, 0x4D, 0xDD, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x05, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x50, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0xDD, 0xD4, 0xF4, 0x44, 0xF4, 0x4F, 0x44, 0x4F, 0x4D, 0xDD, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x05, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x50, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0xDD, 0xD4, 0xFF, 0xFF, 0xF4, 0x44, 0x44, 0x4F, 0x4D, 0xDD, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x05, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x50, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0xDD, 0xD4, 0xF4, 0x44, 0xF4, 0x44, 0x4F, 0xF4, 0x4D, 0xDD, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x05, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x50, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0xDD, 0xD4, 0xF4, 0x44, 0xF4, 0x44, 0xF4, 0x44, 0x4D, 0xDD, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x05, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x50, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0xDD, 0xD4, 0x4F, 0x4F, 0x44, 0x4F, 0x44, 0x44, 0x4D, 0xDD, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x05, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x50, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0xDD, 0xD4, 0x44, 0xF4, 0x44, 0x4F, 0xFF, 0xFF, 0x4D, 0xDD, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x05, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x50, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0xDD, 0xD4, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x4D, 0xDD, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x05, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x50, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xD4, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x05, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x50, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x05, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x50, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xD4, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x05, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x50, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x05, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x50, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x05, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x50, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x05, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x50, 0x44, 0x44, 0x44, 0x4F, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0xFF, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x05, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x50, 0x44, 0x44, 0x44, 0xF4, 0xF4, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x4F, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x05, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x50, 0x44, 0x44, 0x4F, 0x44, 0x4F, 0x44, 0xFF, 0xFF, 0x44, 0x44, 0xFF, 0xF4, 0x44, 0x4F, 0x44, 0x44, 0xFF, 0xF4, 0x44, 0x4F, 0xFF, 0x44, 0x44, 0x44, 0x05, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x50, 0x44, 0x44, 0x4F, 0x44, 0x4F, 0x44, 0xF4, 0x44, 0xF4, 0x44, 0x44, 0x4F, 0x44, 0x4F, 0x44, 0x4F, 0x44, 0x4F, 0x44, 0xF4, 0x44, 0xF4, 0x44, 0x44, 0x05, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x50, 0x44, 0x44, 0x4F, 0xFF, 0xFF, 0x44, 0xF4, 0x44, 0xF4, 0x44, 0xFF, 0xFF, 0x44, 0x4F, 0x44, 0x4F, 0x44, 0x4F, 0x44, 0xF4, 0x44, 0xF4, 0x44, 0x44, 0x05, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x50, 0x44, 0x44, 0x4F, 0x44, 0x4F, 0x44, 0xF4, 0x44, 0xF4, 0x4F, 0x44, 0x4F, 0x44, 0x4F, 0x44, 0x4F, 0x44, 0x4F, 0x44, 0x4F, 0xFF, 0xF4, 0x44, 0x44, 0x05, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x50, 0x44, 0x44, 0x4F, 0x44, 0x4F, 0x44, 0xF4, 0x44, 0xF4, 0x44, 0xFF, 0xFF, 0x44, 0xFF, 0xF4, 0x44, 0xFF, 0xF4, 0x44, 0x44, 0x44, 0xF4, 0x44, 0x44, 0x05, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x50, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x4F, 0xFF, 0x44, 0x44, 0x44, 0x05, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x50, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x05, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x50, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x05, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x50, 0x44, 0x4F, 0xFF, 0xF4, 0x44, 0x4F, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x4F, 0xFF, 0xF4, 0x44, 0x44, 0x44, 0x44, 0x4F, 0xF4, 0x44, 0x05, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x50, 0x44, 0x4F, 0x44, 0x4F, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x4F, 0x44, 0x4F, 0x44, 0x44, 0x44, 0x44, 0x44, 0xF4, 0x44, 0x05, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x50, 0x44, 0x4F, 0x44, 0x4F, 0x44, 0xFF, 0x44, 0x44, 0xFF, 0xFF, 0x44, 0x4F, 0xFF, 0x44, 0x4F, 0x44, 0x4F, 0x44, 0x4F, 0xFF, 0x44, 0x44, 0xF4, 0x44, 0x05, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x50, 0x44, 0x4F, 0xFF, 0xF4, 0x44, 0x4F, 0x44, 0x4F, 0x44, 0x44, 0x44, 0xF4, 0x44, 0xF4, 0x4F, 0xFF, 0xF4, 0x44, 0x44, 0x44, 0xF4, 0x44, 0xF4, 0x44, 0x05, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x50, 0x44, 0x4F, 0x44, 0x44, 0x44, 0x4F, 0x44, 0x4F, 0x44, 0x44, 0x44, 0xF4, 0x44, 0xF4, 0x4F, 0x44, 0x44, 0x44, 0x4F, 0xFF, 0xF4, 0x44, 0xF4, 0x44, 0x05, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x50, 0x44, 0x4F, 0x44, 0x44, 0x44, 0x4F, 0x44, 0x4F, 0x44, 0x44, 0x44, 0xF4, 0x44, 0xF4, 0x4F, 0x44, 0x44, 0x44, 0xF4, 0x44, 0xF4, 0x44, 0xF4, 0x44, 0x05, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x50, 0x44, 0x4F, 0x44, 0x44, 0x44, 0xFF, 0xF4, 0x44, 0xFF, 0xFF, 0x44, 0x4F, 0xFF, 0x44, 0x4F, 0x44, 0x44, 0x44, 0x4F, 0xFF, 0xF4, 0x4F, 0xFF, 0x44, 0x05, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x50, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x05, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x50, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x05, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x50, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x05, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0xDD, 0x44, 0xDD, 0x44, 0xDD, 0x44, 0xDD, 0x44, 0xDD, 0x44, 0x05, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0xDD, 0x44, 0xDD, 0x44, 0xDD, 0x44, 0xDD, 0x44, 0xDD, 0x44, 0x05, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0xDD, 0x44, 0xDD, 0x44, 0xDD, 0x44, 0xDD, 0x44, 0xDD, 0x44, 0x05, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
};
|
263
vga/render.c
Normal file
263
vga/render.c
Normal file
@ -0,0 +1,263 @@
|
||||
#include <string.h>
|
||||
#include <pico/stdlib.h>
|
||||
#include <hardware/timer.h>
|
||||
#include "common/config.h"
|
||||
#include "common/flash.h"
|
||||
#include "common/dmacopy.h"
|
||||
#include "vga/vgabuf.h"
|
||||
#include "vga/render.h"
|
||||
#include "vga/vgaout.h"
|
||||
|
||||
uint16_t text_fore;
|
||||
uint16_t text_back;
|
||||
uint16_t text_border;
|
||||
|
||||
compat_t machinefont = MACHINE_INVALID;
|
||||
bool userfont = false;
|
||||
|
||||
uint16_t DELAYED_COPY_DATA(mono_colors)[14] = {
|
||||
_RGB(0x00, 0x00, 0x00), _RGB(0xFF, 0xFF, 0xFF), // White Normal
|
||||
_RGB(0xFF, 0xFF, 0xFF), _RGB(0x00, 0x00, 0x00), // White Inverse
|
||||
_RGB(0x00, 0x00, 0x00), _RGB(0xFE, 0x7F, 0x00), // Amber Normal
|
||||
_RGB(0xFE, 0x7F, 0x00), _RGB(0x00, 0x00, 0x00), // Amber Inverse
|
||||
_RGB(0x00, 0x00, 0x00), _RGB(0x00, 0xBF, 0x00), // Green Normal
|
||||
_RGB(0x00, 0xBF, 0x00), _RGB(0x00, 0x00, 0x00), // Green Inverse
|
||||
_RGB(0x35, 0x28, 0x79), _RGB(0x6C, 0x5E, 0xB5), // Commodore
|
||||
};
|
||||
|
||||
// Initialize the character generator ROM
|
||||
static void DELAYED_COPY_CODE(switch_font)() {
|
||||
if(userfont) {
|
||||
return;
|
||||
} else if(romx_changed) {
|
||||
memcpy32(character_rom, (void*)FLASH_FONT(romx_textbank), 4096);
|
||||
} else if(current_machine != machinefont) {
|
||||
switch(current_machine) {
|
||||
default:
|
||||
case MACHINE_II:
|
||||
memcpy32(character_rom, (void*)FLASH_FONT_APPLE_II, 4096);
|
||||
break;
|
||||
case MACHINE_IIE:
|
||||
memcpy32(character_rom, (void*)FLASH_FONT_APPLE_IIE, 4096);
|
||||
break;
|
||||
case MACHINE_IIGS:
|
||||
memcpy32(character_rom, (void*)FLASH_FONT_APPLE_IIGS, 4096);
|
||||
break;
|
||||
case MACHINE_PRAVETZ:
|
||||
memcpy32(character_rom, (void*)FLASH_FONT_PRAVETZ, 4096);
|
||||
break;
|
||||
}
|
||||
machinefont = current_machine;
|
||||
}
|
||||
}
|
||||
|
||||
uint16_t status_timeout = 900;
|
||||
uint8_t status_line[81];
|
||||
|
||||
void DELAYED_COPY_CODE(update_status_right)(const char *str) {
|
||||
uint i, len;
|
||||
|
||||
if(str != NULL) {
|
||||
len = strlen(str);
|
||||
} else {
|
||||
len = 0;
|
||||
}
|
||||
|
||||
if(len < 80) {
|
||||
memset(status_line, ' ', 80 - len);
|
||||
} else {
|
||||
len = 80;
|
||||
}
|
||||
|
||||
for(i = 0; i < len; i++) {
|
||||
status_line[(80-len) + i] = str[i];
|
||||
}
|
||||
|
||||
status_timeout = 900;
|
||||
}
|
||||
|
||||
void DELAYED_COPY_CODE(update_status_left)(const char *str) {
|
||||
uint i, len;
|
||||
|
||||
if(str != NULL) {
|
||||
len = strlen(str);
|
||||
} else {
|
||||
len = 0;
|
||||
}
|
||||
|
||||
if(len < 80) {
|
||||
memset(status_line + len, ' ', 80 - len);
|
||||
} else {
|
||||
len = 80;
|
||||
}
|
||||
|
||||
for(i = 0; i < len; i++) {
|
||||
status_line[i] = str[i];
|
||||
}
|
||||
|
||||
status_timeout = 900;
|
||||
}
|
||||
|
||||
void DELAYED_COPY_CODE(render_init)() {
|
||||
int i;
|
||||
|
||||
switch_font();
|
||||
|
||||
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_FONT_APPLE_IIE, 4096);
|
||||
memset(status_line, 0, sizeof(status_line));
|
||||
|
||||
render_test_init();
|
||||
}
|
||||
|
||||
// Skip lines to center vertically or blank the screen
|
||||
void DELAYED_COPY_CODE(render_border)(uint count) {
|
||||
struct vga_scanline *sl = vga_prepare_scanline();
|
||||
uint sl_pos = 0;
|
||||
|
||||
while(sl_pos < VGA_WIDTH/16) {
|
||||
sl->data[sl_pos] = (text_border|THEN_EXTEND_7) | ((text_border|THEN_EXTEND_7) << 16); // 8 pixels per word
|
||||
sl_pos++;
|
||||
}
|
||||
|
||||
sl->length = sl_pos;
|
||||
sl->repeat_count = count - 1;
|
||||
vga_submit_scanline(sl);
|
||||
}
|
||||
|
||||
uint32_t screentimeout = 0;
|
||||
uint32_t testdone = 0;
|
||||
|
||||
void DELAYED_COPY_CODE(render_loop)() {
|
||||
for(;;) {
|
||||
config_handler();
|
||||
|
||||
#if 0
|
||||
if((busactive == 0) && (screentimeout > (15 * 60))) {
|
||||
vga_prepare_frame();
|
||||
render_border(VGA_HEIGHT);
|
||||
memset(status_line, 0, sizeof(status_line));
|
||||
status_timeout = 0;
|
||||
vga_dpms_sleep();
|
||||
while(busactive == 0);
|
||||
vga_dpms_wake();
|
||||
} else {
|
||||
if(busactive == 0) {
|
||||
screentimeout++;
|
||||
if(screentimeout == 5) {
|
||||
update_status_right("Going to sleep...");
|
||||
}
|
||||
} else {
|
||||
if(screentimeout >= 5) {
|
||||
// Clear the sleep mode message
|
||||
memset(status_line, 0, sizeof(status_line));
|
||||
status_timeout = 0;
|
||||
}
|
||||
screentimeout = 0;
|
||||
}
|
||||
busactive = 0;
|
||||
#endif
|
||||
|
||||
if(romx_changed || (machinefont != current_machine)) {
|
||||
switch_font();
|
||||
romx_changed = 0;
|
||||
machinefont = current_machine;
|
||||
}
|
||||
|
||||
update_text_flasher();
|
||||
|
||||
if(!(mono_palette & 0x8)) {
|
||||
if((current_machine == MACHINE_IIGS) && !(soft_switches & SOFTSW_MONOCHROME)) {
|
||||
text_fore = lores_palette[APPLE_FORE];
|
||||
text_back = lores_palette[APPLE_BACK];
|
||||
text_border = lores_palette[APPLE_BORDER];
|
||||
} else {
|
||||
text_fore = mono_colors[1];
|
||||
text_back = mono_colors[0];
|
||||
text_border = mono_colors[0];
|
||||
}
|
||||
} else if(mono_palette == 0xF) {
|
||||
text_fore = lores_palette[TERMINAL_FORE];
|
||||
text_back = lores_palette[TERMINAL_BACK];
|
||||
text_border = lores_palette[TERMINAL_BORDER];
|
||||
} else {
|
||||
int palette = mono_palette & 0x7;
|
||||
text_fore = mono_colors[palette*2+1];
|
||||
text_back = mono_colors[palette*2];
|
||||
text_border = (palette == 0x6) ? text_fore : text_back;
|
||||
}
|
||||
|
||||
if(internal_flags & IFLAGS_TEST) {
|
||||
render_testpattern();
|
||||
// Automatically dismiss the test pattern when the Apple II is seen.
|
||||
if(((soft_switches & SOFTSW_MODE_MASK) != 0) && (testdone == 0)) {
|
||||
internal_flags &= ~IFLAGS_TEST;
|
||||
testdone = 1;
|
||||
render_about_init();
|
||||
}
|
||||
} else if(soft_switches & SOFTSW_TERMINAL) {
|
||||
render_terminal();
|
||||
#if defined(ANALOG_GS) || defined(OVERCLOCKED)
|
||||
} else if(soft_switches & SOFTSW_SHR) {
|
||||
render_shr();
|
||||
#endif
|
||||
} else {
|
||||
vga_prepare_frame();
|
||||
|
||||
render_border(24);
|
||||
if(status_line[0] != 0) {
|
||||
render_status_line();
|
||||
render_border(16);
|
||||
} else {
|
||||
render_border(32);
|
||||
}
|
||||
|
||||
switch(soft_switches & SOFTSW_MODE_MASK) {
|
||||
case 0:
|
||||
if(soft_switches & SOFTSW_DGR) {
|
||||
render_dgr();
|
||||
} else {
|
||||
render_lores();
|
||||
}
|
||||
break;
|
||||
case SOFTSW_MIX_MODE:
|
||||
if((soft_switches & (SOFTSW_80COL | SOFTSW_DGR)) == (SOFTSW_80COL | SOFTSW_DGR)) {
|
||||
render_mixed_dgr();
|
||||
} else {
|
||||
render_mixed_lores();
|
||||
}
|
||||
break;
|
||||
case SOFTSW_HIRES_MODE:
|
||||
if(soft_switches & SOFTSW_DGR) {
|
||||
render_dhgr();
|
||||
} else {
|
||||
render_hires();
|
||||
}
|
||||
break;
|
||||
case SOFTSW_HIRES_MODE|SOFTSW_MIX_MODE:
|
||||
if((soft_switches & (SOFTSW_80COL | SOFTSW_DGR)) == (SOFTSW_80COL | SOFTSW_DGR)) {
|
||||
render_mixed_dhgr();
|
||||
} else {
|
||||
render_mixed_hires();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
render_text();
|
||||
break;
|
||||
}
|
||||
|
||||
render_border(48);
|
||||
}
|
||||
#if 0
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
82
vga/render.h
Normal file
82
vga/render.h
Normal file
@ -0,0 +1,82 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
// Uncomment to enable test patter generator
|
||||
#define RENDER_TEST_PATTERN
|
||||
|
||||
extern uint16_t lores_palette[16];
|
||||
extern uint16_t text_fore, text_back, text_border;
|
||||
extern uint8_t status_line[81];
|
||||
|
||||
extern void update_status_left(const char *str);
|
||||
extern void update_status_right(const char *str);
|
||||
|
||||
extern void render_init();
|
||||
extern void render_loop();
|
||||
|
||||
extern void render_testpattern();
|
||||
extern void render_test_init();
|
||||
extern void render_about_init();
|
||||
extern void render_test_sleep();
|
||||
|
||||
extern void update_text_flasher();
|
||||
extern void render_text();
|
||||
extern void render_text40_line(bool p2, unsigned int line);
|
||||
extern void render_text80_line(bool p2, unsigned int line);
|
||||
extern void render_status_line();
|
||||
|
||||
extern void render_terminal();
|
||||
extern void render_terminal_line(unsigned int line);
|
||||
|
||||
extern void render_border(uint count);
|
||||
|
||||
extern void render_lores();
|
||||
extern void render_mixed_lores();
|
||||
|
||||
extern void render_hires();
|
||||
extern void render_mixed_hires();
|
||||
|
||||
extern void render_dhgr();
|
||||
extern void render_mixed_dhgr();
|
||||
|
||||
extern void render_dgr();
|
||||
extern void render_mixed_dgr();
|
||||
|
||||
extern void render_shr();
|
||||
|
||||
extern volatile uint_fast32_t text_flasher_mask;
|
||||
|
||||
extern void vga_init();
|
||||
extern void vga_deinit();
|
||||
|
||||
#ifdef ANALOG_GS
|
||||
#define _RGB(r, g, b) ( \
|
||||
(((((uint)(r) * 256 / 18) + 256) / 256) << 8) | \
|
||||
(((((uint)(g) * 256 / 18) + 256) / 256) << 4) | \
|
||||
((((uint)(b) * 256 / 18) + 256) / 256) \
|
||||
)
|
||||
#else
|
||||
#define _RGB(r, g, b) ( \
|
||||
(((((uint)(r) * 256 / 36) + 128) / 256) << 6) | \
|
||||
(((((uint)(g) * 256 / 36) + 128) / 256) << 3) | \
|
||||
((((uint)(b) * 256 / 36) + 128) / 256) \
|
||||
)
|
||||
#endif
|
||||
|
||||
#define RGB_BLACK _RGB(0x00,0x00,0x00)
|
||||
#define RGB_MAGENTA _RGB(0x6c,0x00,0x6c)
|
||||
#define RGB_DBLUE _RGB(0x00,0x00,0xb4)
|
||||
#define RGB_HVIOLET _RGB(0xb4,0x24,0xfc)
|
||||
#define RGB_DGREEN _RGB(0x00,0x48,0x00)
|
||||
#define RGB_DGRAY _RGB(0x48,0x48,0x48)
|
||||
#define RGB_HBLUE _RGB(0x00,0x90,0xfc)
|
||||
#define RGB_LBLUE _RGB(0x6c,0x6c,0xfc)
|
||||
#define RGB_BROWN _RGB(0x24,0x24,0x00)
|
||||
#define RGB_HORANGE _RGB(0xfc,0x48,0x00)
|
||||
#define RGB_LGRAY _RGB(0x90,0x90,0x90)
|
||||
#define RGB_PINK _RGB(0xfc,0x6c,0xfc)
|
||||
#define RGB_HGREEN _RGB(0x00,0xd8,0x24)
|
||||
#define RGB_YELLOW _RGB(0xd8,0xd8,0x00)
|
||||
#define RGB_AQUA _RGB(0x90,0xfc,0xb4)
|
||||
#define RGB_WHITE _RGB(0xff,0xff,0xff)
|
72
vga/render_80col.c
Normal file
72
vga/render_80col.c
Normal file
@ -0,0 +1,72 @@
|
||||
#include <pico/stdlib.h>
|
||||
#include "common/config.h"
|
||||
#include "vga/vgabuf.h"
|
||||
#include "vga/render.h"
|
||||
#include "vga/vgaout.h"
|
||||
|
||||
static inline uint_fast8_t char_terminal_bits(uint_fast8_t ch, uint_fast8_t glyph_line) {
|
||||
uint_fast8_t bits = terminal_character_rom[((uint_fast16_t)ch << 3) | glyph_line];
|
||||
if(ch & 0x80) {
|
||||
// normal character
|
||||
return bits & 0x7f;
|
||||
}
|
||||
|
||||
if((bits & 0x80) == 0) {
|
||||
// inverse character
|
||||
return bits ^ 0x7f;
|
||||
} else {
|
||||
// flashing character
|
||||
return (bits ^ text_flasher_mask) & 0x7f;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void DELAYED_COPY_CODE(render_terminal)() {
|
||||
for(int line=0; line < 24; line++) {
|
||||
render_terminal_line(line);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void DELAYED_COPY_CODE(render_terminal_line)(unsigned int line) {
|
||||
const uint8_t *page = (const uint8_t *)terminal_memory;
|
||||
const uint8_t *line_buf = page + (line * 80);
|
||||
|
||||
for(uint glyph_line=0; glyph_line < 8; glyph_line++) {
|
||||
struct vga_scanline *sl = vga_prepare_scanline();
|
||||
uint sl_pos = 0;
|
||||
|
||||
// Pad 40 pixels on the left to center horizontally
|
||||
sl->data[sl_pos++] = (text_border|THEN_EXTEND_31) | ((text_border|THEN_EXTEND_7) << 16); // 16 pixels per word
|
||||
|
||||
for(uint col=0; col < 80; ) {
|
||||
// Grab 14 pixels from the next two characters
|
||||
uint32_t bits_a = char_terminal_bits(line_buf[col], glyph_line);
|
||||
col++;
|
||||
uint32_t bits_b = char_terminal_bits(line_buf[col], glyph_line);
|
||||
col++;
|
||||
|
||||
uint32_t bits = (bits_a << 7) | bits_b;
|
||||
|
||||
// Translate each pair of bits into a pair of pixels
|
||||
for(int i=0; i < 7; i++) {
|
||||
uint32_t pixeldata = (bits & 0x2000) ? (text_fore) : (text_back);
|
||||
pixeldata |= (bits & 0x1000) ?
|
||||
(((uint32_t)text_fore) << 16) :
|
||||
(((uint32_t)text_back) << 16);
|
||||
bits <<= 2;
|
||||
|
||||
sl->data[sl_pos] = pixeldata;
|
||||
sl_pos++;
|
||||
}
|
||||
}
|
||||
|
||||
// Pad 40 pixels on the right to center horizontally
|
||||
sl->data[sl_pos++] = (text_border|THEN_EXTEND_31) | ((text_border|THEN_EXTEND_7) << 16); // 16 pixels per word
|
||||
|
||||
sl->length = sl_pos;
|
||||
sl->repeat_count = 1;
|
||||
vga_submit_scanline(sl);
|
||||
}
|
||||
}
|
||||
|
102
vga/render_dgr.c
Normal file
102
vga/render_dgr.c
Normal file
@ -0,0 +1,102 @@
|
||||
#include <pico/stdlib.h>
|
||||
#include "common/config.h"
|
||||
#include "vga/vgabuf.h"
|
||||
#include "vga/render.h"
|
||||
#include "vga/vgaout.h"
|
||||
|
||||
//#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 lores_palette[16];
|
||||
extern uint16_t lores_dot_pattern[16];
|
||||
|
||||
static void render_dgr_line(bool p2, uint line);
|
||||
|
||||
void DELAYED_COPY_CODE(render_dgr)() {
|
||||
for(uint line=0; line < 24; line++) {
|
||||
render_dgr_line(PAGE2SEL, line);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void DELAYED_COPY_CODE(render_mixed_dgr)() {
|
||||
for(uint line=0; line < 20; line++) {
|
||||
render_dgr_line(PAGE2SEL, line);
|
||||
}
|
||||
|
||||
for(uint line=20; line < 24; line++) {
|
||||
if(soft_switches & SOFTSW_80COL) {
|
||||
render_text80_line(PAGE2SEL, line);
|
||||
} else {
|
||||
render_text40_line(PAGE2SEL, line);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void DELAYED_COPY_CODE(render_dgr_line)(bool p2, uint line) {
|
||||
// Construct two scanlines for the two different colored cells at the same time
|
||||
struct vga_scanline *sl1 = vga_prepare_scanline();
|
||||
struct vga_scanline *sl2 = vga_prepare_scanline();
|
||||
uint sl_pos = 0;
|
||||
uint i, j;
|
||||
uint32_t color1, color2, color3, color4;
|
||||
|
||||
const uint8_t *line_bufa = (const uint8_t *)((p2 ? text_p2 : text_p1) + ((line & 0x7) << 7) + (((line >> 3) & 0x3) * 40));
|
||||
const uint8_t *line_bufb = (const uint8_t *)((p2 ? text_p4 : text_p3) + ((line & 0x7) << 7) + (((line >> 3) & 0x3) * 40));
|
||||
|
||||
// Pad 40 pixels on the left to center horizontally
|
||||
sl1->data[sl_pos] = (text_border|THEN_EXTEND_31) | ((text_border|THEN_EXTEND_7) << 16); // 16 pixels per word
|
||||
sl2->data[sl_pos] = (text_border|THEN_EXTEND_31) | ((text_border|THEN_EXTEND_7) << 16); // 16 pixels per word
|
||||
sl_pos++;
|
||||
|
||||
if((soft_switches & SOFTSW_MONOCHROME) || (mono_palette & 0x8)) {
|
||||
for(i = 0; i < 40; i++) {
|
||||
color1 = lores_dot_pattern[line_bufb[i] & 0xf] << 21;
|
||||
color2 = lores_dot_pattern[(line_bufb[i] >> 4) & 0xf] << 21;
|
||||
color1 |= lores_dot_pattern[line_bufa[i] & 0xf] << 7;
|
||||
color2 |= lores_dot_pattern[(line_bufa[i] >> 4) & 0xf] << 7;
|
||||
|
||||
for(j = 0; j < 7; j++) {
|
||||
uint32_t pixeldata;
|
||||
|
||||
pixeldata = (color1 & 0x8000000) ? (text_fore) : (text_back);
|
||||
pixeldata |= (color1 & 0x4000000) ? ((text_fore) << 16) : ((text_back) << 16);
|
||||
color1 <<= 2;
|
||||
sl1->data[sl_pos] = pixeldata;
|
||||
|
||||
pixeldata = (color2 & 0x8000000) ? (text_fore) : (text_back);
|
||||
pixeldata |= (color2 & 0x4000000) ? ((text_fore) << 16) : ((text_back) << 16);
|
||||
sl2->data[sl_pos] = pixeldata;
|
||||
color2 <<= 2;
|
||||
|
||||
sl_pos++;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for(i=0; i < 40; i++) {
|
||||
color1 = lores_palette[line_bufb[i] & 0xf];
|
||||
color2 = lores_palette[(line_bufb[i] >> 4) & 0xf];
|
||||
color3 = lores_palette[line_bufa[i] & 0xf];
|
||||
color4 = lores_palette[(line_bufa[i] >> 4) & 0xf];
|
||||
|
||||
// Each double lores pixel is 7 double hires pixels, or 7 VGA pixels wide
|
||||
sl1->data[sl_pos] = (color1|THEN_EXTEND_6) | ((color3|THEN_EXTEND_6) << 16);
|
||||
sl2->data[sl_pos] = (color2|THEN_EXTEND_6) | ((color4|THEN_EXTEND_6) << 16);
|
||||
sl_pos++;
|
||||
}
|
||||
}
|
||||
|
||||
// Pad 40 pixels on the right to center horizontally
|
||||
sl1->data[sl_pos] = (text_border|THEN_EXTEND_31) | ((text_border|THEN_EXTEND_7) << 16); // 16 pixels per word
|
||||
sl2->data[sl_pos] = (text_border|THEN_EXTEND_31) | ((text_border|THEN_EXTEND_7) << 16); // 16 pixels per word
|
||||
sl_pos++;
|
||||
|
||||
sl1->length = sl_pos;
|
||||
sl1->repeat_count = 7;
|
||||
vga_submit_scanline(sl1);
|
||||
|
||||
sl2->length = sl_pos;
|
||||
sl2->repeat_count = 7;
|
||||
vga_submit_scanline(sl2);
|
||||
}
|
132
vga/render_dhgr.c
Normal file
132
vga/render_dhgr.c
Normal file
@ -0,0 +1,132 @@
|
||||
#include <pico/stdlib.h>
|
||||
#include "hires_color_patterns.h"
|
||||
#include "hires_dot_patterns.h"
|
||||
#include "common/config.h"
|
||||
#include "vga/vgabuf.h"
|
||||
#include "vga/render.h"
|
||||
#include "vga/vgaout.h"
|
||||
|
||||
static void render_dhgr_line(bool p2, uint line);
|
||||
|
||||
uint16_t DELAYED_COPY_DATA(dhgr_palette)[16] = {
|
||||
RGB_BLACK, RGB_DBLUE, RGB_DGREEN, RGB_HBLUE,
|
||||
RGB_BROWN, RGB_LGRAY, RGB_HGREEN, RGB_AQUA,
|
||||
RGB_MAGENTA, RGB_HVIOLET, RGB_DGRAY, RGB_LBLUE,
|
||||
RGB_HORANGE, RGB_PINK, RGB_YELLOW, RGB_WHITE
|
||||
};
|
||||
|
||||
//#define PAGE2SEL (!(soft_switches & SOFTSW_80STORE) && (soft_switches & SOFTSW_PAGE_2))
|
||||
#define PAGE2SEL ((soft_switches & (SOFTSW_80STORE | SOFTSW_PAGE_2)) == SOFTSW_PAGE_2)
|
||||
|
||||
|
||||
static inline uint dhgr_line_to_mem_offset(uint line) {
|
||||
return ((line & 0x07) << 10) | ((line & 0x38) << 4) | (((line & 0xc0) >> 6) * 40);
|
||||
}
|
||||
|
||||
|
||||
void DELAYED_COPY_CODE(render_dhgr)() {
|
||||
for(uint line=0; line < 192; line++) {
|
||||
render_dhgr_line(PAGE2SEL, line);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void DELAYED_COPY_CODE(render_mixed_dhgr)() {
|
||||
for(uint line=0; line < 160; line++) {
|
||||
render_dhgr_line(PAGE2SEL, line);
|
||||
}
|
||||
|
||||
for(uint line=20; line < 24; line++) {
|
||||
if(soft_switches & SOFTSW_80COL) {
|
||||
render_text80_line(PAGE2SEL, line);
|
||||
} else {
|
||||
render_text40_line(PAGE2SEL, line);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void DELAYED_COPY_CODE(render_dhgr_line)(bool p2, uint line) {
|
||||
struct vga_scanline *sl = vga_prepare_scanline();
|
||||
uint sl_pos = 0;
|
||||
uint i;
|
||||
|
||||
const uint8_t *line_mema = (const uint8_t *)((p2 ? hgr_p2 : hgr_p1) + dhgr_line_to_mem_offset(line));
|
||||
const uint8_t *line_memb = (const uint8_t *)((p2 ? hgr_p4 : hgr_p3) + dhgr_line_to_mem_offset(line));
|
||||
|
||||
// Pad 40 pixels on the left to center horizontally
|
||||
sl->data[sl_pos++] = (text_border|THEN_EXTEND_31) | ((text_border|THEN_EXTEND_7) << 16); // 16 pixels per word
|
||||
|
||||
// DHGR is weird. Nuff said.
|
||||
uint32_t dots = 0;
|
||||
uint32_t pixeldata;
|
||||
int j;
|
||||
|
||||
i = 0;
|
||||
while(i < 40) {
|
||||
// Load in the next 28 subpixels
|
||||
dots = (line_memb[i] & 0x7f) << 0;
|
||||
dots |= (line_mema[i] & 0x7f) << 7;
|
||||
i++;
|
||||
dots |= (line_memb[i] & 0x7f) << 14;
|
||||
dots |= (line_mema[i] & 0x7f) << 21;
|
||||
i++;
|
||||
|
||||
if((soft_switches & SOFTSW_MONOCHROME) || (mono_palette & 0x8)) {
|
||||
// Consume 6 pixels (24 subpixel bits)
|
||||
for(j = 0; j < 12; j++) {
|
||||
pixeldata = ((dots & 1) ? (text_fore) : (text_back));
|
||||
dots >>= 1;
|
||||
pixeldata |= (((dots & 1) ? (text_fore) : (text_back))) << 16;
|
||||
dots >>= 1;
|
||||
sl->data[sl_pos++] = pixeldata;
|
||||
}
|
||||
} else {
|
||||
// Consume 6 pixels (24 subpixel bits)
|
||||
for(j = 0; j < 3; j++) {
|
||||
pixeldata = (dhgr_palette[dots & 0xf] | THEN_EXTEND_3);
|
||||
dots >>= 4;
|
||||
pixeldata |= (dhgr_palette[dots & 0xf] | THEN_EXTEND_3) << 16;
|
||||
dots >>= 4;
|
||||
sl->data[sl_pos++] = pixeldata;
|
||||
}
|
||||
}
|
||||
|
||||
// 4 subpixels roll over to the next block
|
||||
// Load in the next 28 subpixels
|
||||
dots |= (line_memb[i] & 0x7f) << 4;
|
||||
dots |= (line_mema[i] & 0x7f) << 11;
|
||||
i++;
|
||||
dots |= (line_memb[i] & 0x7f) << 18;
|
||||
dots |= (line_mema[i] & 0x7f) << 25;
|
||||
i++;
|
||||
|
||||
if(soft_switches & SOFTSW_MONOCHROME) {
|
||||
// Consume 8 pixels (32 subpixel bits)
|
||||
for(j = 0; j < 16; j++) {
|
||||
pixeldata = ((dots & 1) ? (text_fore) : (text_back));
|
||||
dots >>= 1;
|
||||
pixeldata |= (((dots & 1) ? (text_fore) : (text_back))) << 16;
|
||||
dots >>= 1;
|
||||
sl->data[sl_pos++] = pixeldata;
|
||||
}
|
||||
} else {
|
||||
// Consume 8 pixels (32 subpixel bits)
|
||||
for(j = 0; j < 4; j++) {
|
||||
pixeldata = (dhgr_palette[dots & 0xf] | THEN_EXTEND_3);
|
||||
dots >>= 4;
|
||||
pixeldata |= (dhgr_palette[dots & 0xf] | THEN_EXTEND_3) << 16;
|
||||
dots >>= 4;
|
||||
sl->data[sl_pos++] = pixeldata;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Pad 40 pixels on the right to center horizontally
|
||||
sl->data[sl_pos++] = (text_border|THEN_EXTEND_31) | ((text_border|THEN_EXTEND_7) << 16); // 16 pixels per word
|
||||
|
||||
sl->length = sl_pos;
|
||||
sl->repeat_count = 1;
|
||||
vga_submit_scanline(sl);
|
||||
}
|
||||
|
113
vga/render_hires.c
Normal file
113
vga/render_hires.c
Normal file
@ -0,0 +1,113 @@
|
||||
#include <pico/stdlib.h>
|
||||
#include "common/config.h"
|
||||
#include "vga/hires_color_patterns.h"
|
||||
#include "vga/hires_dot_patterns.h"
|
||||
#include "vga/vgabuf.h"
|
||||
#include "vga/render.h"
|
||||
#include "vga/vgaout.h"
|
||||
|
||||
//#define PAGE2SEL (!(soft_switches & SOFTSW_80STORE) && (soft_switches & SOFTSW_PAGE_2))
|
||||
#define PAGE2SEL ((soft_switches & (SOFTSW_80STORE | SOFTSW_PAGE_2)) == SOFTSW_PAGE_2)
|
||||
|
||||
static void render_hires_line(bool p2, uint line);
|
||||
|
||||
static inline uint hires_line_to_mem_offset(uint line) {
|
||||
return ((line & 0x07) << 10) | ((line & 0x38) << 4) | (((line & 0xc0) >> 6) * 40);
|
||||
}
|
||||
|
||||
|
||||
void DELAYED_COPY_CODE(render_hires)() {
|
||||
for(uint line=0; line < 192; line++) {
|
||||
render_hires_line(PAGE2SEL, line);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void DELAYED_COPY_CODE(render_mixed_hires)() {
|
||||
for(uint line=0; line < 160; line++) {
|
||||
render_hires_line(PAGE2SEL, line);
|
||||
}
|
||||
|
||||
for(uint line=20; line < 24; line++) {
|
||||
if(soft_switches & SOFTSW_80COL) {
|
||||
render_text80_line(PAGE2SEL, line);
|
||||
} else {
|
||||
render_text40_line(PAGE2SEL, line);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void DELAYED_COPY_CODE(render_hires_line)(bool p2, uint line) {
|
||||
struct vga_scanline *sl = vga_prepare_scanline();
|
||||
uint sl_pos = 0;
|
||||
|
||||
const uint8_t *line_mem = (const uint8_t *)((p2 ? hgr_p2 : hgr_p1) + hires_line_to_mem_offset(line));
|
||||
|
||||
// Pad 40 pixels on the left to center horizontally
|
||||
sl->data[sl_pos++] = (text_border|THEN_EXTEND_31) | ((text_border|THEN_EXTEND_7) << 16); // 16 pixels per word
|
||||
|
||||
// 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.
|
||||
//
|
||||
// For each pixel, inspect a window of 8 dots around the pixel to determine the
|
||||
// precise dot locations and colors.
|
||||
//
|
||||
// Dots would be scanned out to the CRT from MSB to LSB (left to right here):
|
||||
//
|
||||
// previous | next
|
||||
// dots | dots
|
||||
// +-------------------+--------------------------------------------------+
|
||||
// dots: | 31 | 30 | 29 | 28 | 27 | 26 | 25 | 24 | 23 | ... | 14 | 13 | 12 | ...
|
||||
// | | | |
|
||||
// \______________|_________|______________/
|
||||
// | |
|
||||
// \_________/
|
||||
// current
|
||||
// pixel
|
||||
uint32_t dots = 0;
|
||||
uint oddness = 0;
|
||||
uint i, j;
|
||||
|
||||
// Load in the first 14 dots
|
||||
dots |= (uint32_t)hires_dot_patterns[line_mem[0]] << 15;
|
||||
|
||||
for(i=1; i < 41; i++) {
|
||||
// Load in the next 14 dots
|
||||
uint b = (i < 40) ? line_mem[i] : 0;
|
||||
if(b & 0x80) {
|
||||
// Extend the last bit from the previous byte
|
||||
dots |= (dots & (1u << 15)) >> 1;
|
||||
}
|
||||
dots |= (uint32_t)hires_dot_patterns[b] << 1;
|
||||
|
||||
if((soft_switches & SOFTSW_MONOCHROME) || (mono_palette & 0x8)) {
|
||||
// Consume 14 dots
|
||||
for(j = 0; j < 7; j++) {
|
||||
uint32_t pixeldata = (dots & 0x40000000) ? (text_fore) : (text_back);
|
||||
pixeldata |= (dots & 0x20000000) ?
|
||||
((text_fore) << 16) :
|
||||
((text_back) << 16);
|
||||
dots <<= 2;
|
||||
sl->data[sl_pos] = pixeldata;
|
||||
sl_pos++;
|
||||
}
|
||||
} else {
|
||||
// Consume 14 dots
|
||||
for(uint j=0; j < 7; j++) {
|
||||
uint dot_pattern = oddness | ((dots >> 24) & 0xff);
|
||||
sl->data[sl_pos] = hires_color_patterns[dot_pattern];
|
||||
sl_pos++;
|
||||
dots <<= 2;
|
||||
oddness ^= 0x100;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Pad 40 pixels on the right to center horizontally
|
||||
sl->data[sl_pos++] = (text_border|THEN_EXTEND_31) | ((text_border|THEN_EXTEND_7) << 16); // 16 pixels per word
|
||||
|
||||
sl->length = sl_pos;
|
||||
sl->repeat_count = 1;
|
||||
vga_submit_scanline(sl);
|
||||
}
|
123
vga/render_lores.c
Normal file
123
vga/render_lores.c
Normal file
@ -0,0 +1,123 @@
|
||||
#include <pico/stdlib.h>
|
||||
#include "common/config.h"
|
||||
#include "vga/vgabuf.h"
|
||||
#include "vga/render.h"
|
||||
#include "vga/vgaout.h"
|
||||
|
||||
uint16_t DELAYED_COPY_DATA(lores_dot_pattern)[16] = {
|
||||
0x0000,
|
||||
0x2222,
|
||||
0x1111,
|
||||
0x3333,
|
||||
0x0888,
|
||||
0x2AAA,
|
||||
0x1999,
|
||||
0x3BBB,
|
||||
0x0444,
|
||||
0x2666,
|
||||
0x1555,
|
||||
0x3777,
|
||||
0x0CCC,
|
||||
0x2EEE,
|
||||
0x1DDD,
|
||||
0x3FFF,
|
||||
};
|
||||
|
||||
uint16_t DELAYED_COPY_DATA(lores_palette)[16] = {
|
||||
RGB_BLACK, RGB_MAGENTA, RGB_DBLUE, RGB_HVIOLET,
|
||||
RGB_DGREEN, RGB_DGRAY, RGB_HBLUE, RGB_LBLUE,
|
||||
RGB_BROWN, RGB_HORANGE, RGB_LGRAY, RGB_PINK,
|
||||
RGB_HGREEN, RGB_YELLOW, RGB_AQUA, RGB_WHITE
|
||||
};
|
||||
|
||||
|
||||
static void render_lores_line(bool p2, uint line);
|
||||
|
||||
//#define PAGE2SEL (!(soft_switches & SOFTSW_80STORE) && (soft_switches & SOFTSW_PAGE_2))
|
||||
#define PAGE2SEL ((soft_switches & (SOFTSW_80STORE | SOFTSW_PAGE_2)) == SOFTSW_PAGE_2)
|
||||
|
||||
void DELAYED_COPY_CODE(render_lores)() {
|
||||
for(uint line=0; line < 24; line++) {
|
||||
render_lores_line(PAGE2SEL, line);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void DELAYED_COPY_CODE(render_mixed_lores)() {
|
||||
for(uint line=0; line < 20; line++) {
|
||||
render_lores_line(PAGE2SEL, line);
|
||||
}
|
||||
|
||||
for(uint line=20; line < 24; line++) {
|
||||
if(soft_switches & SOFTSW_80COL) {
|
||||
render_text80_line(PAGE2SEL, line);
|
||||
} else {
|
||||
render_text40_line(PAGE2SEL, line);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void DELAYED_COPY_CODE(render_lores_line)(bool p2, uint line) {
|
||||
// Construct two scanlines for the two different colored cells at the same time
|
||||
struct vga_scanline *sl1 = vga_prepare_scanline();
|
||||
struct vga_scanline *sl2 = vga_prepare_scanline();
|
||||
uint sl_pos = 0;
|
||||
uint i, j;
|
||||
uint32_t color1, color2;
|
||||
|
||||
const uint8_t *line_buf = (const uint8_t *)((p2 ? text_p2 : text_p1) + ((line & 0x7) << 7) + (((line >> 3) & 0x3) * 40));
|
||||
|
||||
// Pad 40 pixels on the left to center horizontally
|
||||
sl1->data[sl_pos] = (text_border|THEN_EXTEND_31) | ((text_border|THEN_EXTEND_7) << 16); // 16 pixels per word
|
||||
sl2->data[sl_pos] = (text_border|THEN_EXTEND_31) | ((text_border|THEN_EXTEND_7) << 16); // 16 pixels per word
|
||||
sl_pos++;
|
||||
|
||||
if((soft_switches & SOFTSW_MONOCHROME) || (mono_palette & 0x8)) {
|
||||
for(i = 0; i < 40; i+=2) {
|
||||
color1 = lores_dot_pattern[line_buf[i] & 0xf] << 14;
|
||||
color2 = lores_dot_pattern[(line_buf[i] >> 4) & 0xf] << 14;
|
||||
color1 |= lores_dot_pattern[line_buf[i+1] & 0xf];
|
||||
color2 |= lores_dot_pattern[(line_buf[i+1] >> 4) & 0xf];
|
||||
|
||||
for(j = 0; j < 14; j++) {
|
||||
uint32_t pixeldata;
|
||||
|
||||
pixeldata = (color1 & 0x8000000) ? (text_fore) : (text_back);
|
||||
pixeldata |= (color1 & 0x4000000) ? ((text_fore) << 16) : ((text_back) << 16);
|
||||
color1 <<= 2;
|
||||
sl1->data[sl_pos] = pixeldata;
|
||||
|
||||
pixeldata = (color2 & 0x8000000) ? (text_fore) : (text_back);
|
||||
pixeldata |= (color2 & 0x4000000) ? ((text_fore) << 16) : ((text_back) << 16);
|
||||
sl2->data[sl_pos] = pixeldata;
|
||||
color2 <<= 2;
|
||||
|
||||
sl_pos++;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for(i = 0; i < 40; i++) {
|
||||
color1 = lores_palette[line_buf[i] & 0xf];
|
||||
color2 = lores_palette[(line_buf[i] >> 4) & 0xf];
|
||||
|
||||
// Each lores pixel is 7 hires pixels, or 14 VGA pixels wide
|
||||
sl1->data[sl_pos] = (color1|THEN_EXTEND_6) | ((color1|THEN_EXTEND_6) << 16);
|
||||
sl2->data[sl_pos] = (color2|THEN_EXTEND_6) | ((color2|THEN_EXTEND_6) << 16);
|
||||
sl_pos++;
|
||||
}
|
||||
}
|
||||
|
||||
// Pad 40 pixels on the right to center horizontally
|
||||
sl1->data[sl_pos] = (text_border|THEN_EXTEND_31) | ((text_border|THEN_EXTEND_7) << 16); // 16 pixels per word
|
||||
sl2->data[sl_pos] = (text_border|THEN_EXTEND_31) | ((text_border|THEN_EXTEND_7) << 16); // 16 pixels per word
|
||||
sl_pos++;
|
||||
|
||||
sl1->length = sl_pos;
|
||||
sl1->repeat_count = 7;
|
||||
vga_submit_scanline(sl1);
|
||||
|
||||
sl2->length = sl_pos;
|
||||
sl2->repeat_count = 7;
|
||||
vga_submit_scanline(sl2);
|
||||
}
|
101
vga/render_shr.c
Normal file
101
vga/render_shr.c
Normal file
@ -0,0 +1,101 @@
|
||||
#include <pico/stdlib.h>
|
||||
#include "common/config.h"
|
||||
#include "vga/hires_color_patterns.h"
|
||||
#include "vga/hires_dot_patterns.h"
|
||||
#include "vga/vgabuf.h"
|
||||
#include "vga/render.h"
|
||||
#include "vga/vgaout.h"
|
||||
|
||||
static void render_shr_line(uint16_t line);
|
||||
|
||||
#ifdef ANALOG_GS
|
||||
#define rgb444(a) (a)
|
||||
#else
|
||||
static inline uint16_t rgb444(uint16_t a) {
|
||||
return ((a & 0xe00) >> 3) | ((a & 0xe0) >> 2) | ((a & 0xe) >> 1);
|
||||
}
|
||||
#endif
|
||||
|
||||
void DELAYED_COPY_CODE(render_shr)() {
|
||||
vga_prepare_frame();
|
||||
|
||||
render_border(40);
|
||||
|
||||
for(uint line=0; line < 200; line++) {
|
||||
render_shr_line(line);
|
||||
}
|
||||
|
||||
render_border(40);
|
||||
}
|
||||
|
||||
static void DELAYED_COPY_CODE(render_shr_line)(uint16_t line) {
|
||||
struct vga_scanline *sl = vga_prepare_scanline();
|
||||
uint sl_pos = 0;
|
||||
uint i;
|
||||
|
||||
uint8_t control = private_memory[0x9D00 + line];
|
||||
uint32_t line_palette_offset = (control & 0xF) << 5;
|
||||
|
||||
volatile uint16_t *shr_palette = (volatile uint16_t*)(private_memory + 0x9E00 + line_palette_offset);
|
||||
volatile uint8_t *line_mem = (volatile uint8_t *)(private_memory + 0x2000 + (line * 160));
|
||||
|
||||
// SHR is weird. Nuff said.
|
||||
uint32_t dots = 0;
|
||||
uint32_t pixeldata;
|
||||
uint16_t color_a = 0, color_b = 0;
|
||||
int j;
|
||||
|
||||
i = 0;
|
||||
if(control & 0x80) { // 640 Pixels
|
||||
while(i < 160) {
|
||||
// Load in the next 2 pixels
|
||||
dots = (line_mem[i++] & 0xff);
|
||||
|
||||
color_a = ((dots >> 4) & 0xf);
|
||||
color_b = ((dots >> 0) & 0xf);
|
||||
|
||||
// Consume 2 pixels
|
||||
pixeldata = rgb444(shr_palette[color_a]) | THEN_EXTEND_1;
|
||||
pixeldata |= (rgb444(shr_palette[color_b]) | THEN_EXTEND_1) << 16;
|
||||
sl->data[sl_pos++] = pixeldata;
|
||||
}
|
||||
} else if(control & 0x40) { // 320 Pixels w/ color fill
|
||||
while(i < 160) {
|
||||
// Load in the next 4 subpixels
|
||||
dots = (line_mem[i++] & 0xff);
|
||||
|
||||
// Consume 2 pixels
|
||||
if(dots & 0xf0) {
|
||||
color_a = ((dots >> 4) & 0xf);
|
||||
} else {
|
||||
color_a = color_b;
|
||||
}
|
||||
if(dots & 0x0f) {
|
||||
color_b = ((dots >> 0) & 0xf);
|
||||
} else {
|
||||
color_b = color_a;
|
||||
}
|
||||
|
||||
pixeldata = rgb444(shr_palette[color_a]) | THEN_EXTEND_1;
|
||||
pixeldata |= (rgb444(shr_palette[color_b]) | THEN_EXTEND_1) << 16;
|
||||
sl->data[sl_pos++] = pixeldata;
|
||||
}
|
||||
} else { // 320 Pixels
|
||||
while(i < 160) {
|
||||
// Load in the next 2 pixels
|
||||
dots = (line_mem[i++] & 0xff);
|
||||
|
||||
color_a = ((dots >> 4) & 0xf);
|
||||
color_b = ((dots >> 0) & 0xf);
|
||||
|
||||
// Consume 2 pixels
|
||||
pixeldata = rgb444(shr_palette[color_a]) | THEN_EXTEND_1;
|
||||
pixeldata |= (rgb444(shr_palette[color_b]) | THEN_EXTEND_1) << 16;
|
||||
sl->data[sl_pos++] = pixeldata;
|
||||
}
|
||||
}
|
||||
|
||||
sl->length = sl_pos;
|
||||
sl->repeat_count = 1;
|
||||
vga_submit_scanline(sl);
|
||||
}
|
298
vga/render_test.c
Normal file
298
vga/render_test.c
Normal file
@ -0,0 +1,298 @@
|
||||
#include <string.h>
|
||||
#include <pico/stdlib.h>
|
||||
#include <hardware/timer.h>
|
||||
#include "common/config.h"
|
||||
#include "vga/vgabuf.h"
|
||||
#include "vga/render.h"
|
||||
#include "vga/vgaout.h"
|
||||
#include "vga/logo.h"
|
||||
#include "common/build.h"
|
||||
|
||||
#include <pico/unique_id.h>
|
||||
|
||||
#define _PIXPAIR(p1, p2) ((uint32_t)(p1) | (((uint32_t)p2) << 16))
|
||||
|
||||
char __attribute__((section(".uninitialized_data."))) error_message[32*24+1];
|
||||
|
||||
void DELAYED_COPY_CODE(render_test_init)() {
|
||||
memset(error_message, ' ', 32*24);
|
||||
memcpy(error_message + 0, "HARDWARE: V2 Analog Rev1", 32);
|
||||
memcpy(error_message + 32, "FIRMWARE: " BUILDSTR, 32);
|
||||
|
||||
memcpy(error_message + 128, " Copyright (C) 2022-2023 ", 32);
|
||||
memcpy(error_message + 160, " David Kuder ", 32);
|
||||
|
||||
memcpy(error_message + 256, " based on ", 32);
|
||||
memcpy(error_message + 288, " AppleII-VGA by Mark Aikens ", 32);
|
||||
|
||||
memcpy(error_message + 416, " no Apple II bus activity ", 32);
|
||||
|
||||
memcpy(error_message + 544, " Turn off power & check ", 32);
|
||||
memcpy(error_message + 576, " for proper card insertion. ", 32);
|
||||
|
||||
memcpy(error_message + 704, " serial number: ", 32);
|
||||
|
||||
// Get Pico's Flash Serial Number (Board ID) and terminating null.
|
||||
memcpy(error_message + 736, " ", 8);
|
||||
pico_get_unique_board_id_string(error_message + 744, 17);
|
||||
memcpy(error_message + 760, " ", 8);
|
||||
}
|
||||
|
||||
// Clear the error message, in case the user sets 0x20 in terminal switches
|
||||
// to show the about screen.
|
||||
void DELAYED_COPY_CODE(render_about_init)() {
|
||||
memset(error_message + 416, ' ', 32);
|
||||
memset(error_message + 544, ' ', 64);
|
||||
}
|
||||
|
||||
static inline uint_fast8_t char_test_bits(uint_fast8_t ch, uint_fast8_t glyph_line) {
|
||||
uint_fast8_t bits = terminal_character_rom[((uint_fast16_t)(ch & 0x7f) << 3) | glyph_line | 0x400];
|
||||
return bits & 0x7f;
|
||||
}
|
||||
|
||||
void DELAYED_COPY_CODE(render_testpattern)() {
|
||||
vga_prepare_frame();
|
||||
|
||||
for(uint line=0; line < VGA_HEIGHT;) {
|
||||
if(line == 19) {
|
||||
render_status_line();
|
||||
line += 16;
|
||||
} else {
|
||||
struct vga_scanline *sl = vga_prepare_scanline();
|
||||
uint sl_pos = 0;
|
||||
|
||||
if((line == 0) || (line == VGA_HEIGHT-1) || (line == 36) || (line == VGA_HEIGHT-36-1)) {
|
||||
for(; sl_pos < VGA_WIDTH/32; sl_pos++) {
|
||||
sl->data[sl_pos] = _PIXPAIR(0x1ff | THEN_EXTEND_15, 0x1ff | THEN_EXTEND_15);
|
||||
}
|
||||
sl->length = sl_pos;
|
||||
} else if(line == 1) {
|
||||
for(uint i=0; i < VGA_WIDTH/4; i++, sl_pos++) {
|
||||
sl->data[sl_pos] = _PIXPAIR(0x1ff, 0);
|
||||
}
|
||||
for(uint i=0; i < VGA_WIDTH/4; i++, sl_pos++) {
|
||||
sl->data[sl_pos] = _PIXPAIR(0, 0x1ff);
|
||||
}
|
||||
|
||||
sl->length = sl_pos;
|
||||
sl->repeat_count = 16;
|
||||
} else if(line == VGA_HEIGHT-36) {
|
||||
for(uint i=0; i < VGA_WIDTH/4; i++, sl_pos++) {
|
||||
sl->data[sl_pos] = _PIXPAIR(0x1ff, 0);
|
||||
}
|
||||
for(uint i=0; i < VGA_WIDTH/4; i++, sl_pos++) {
|
||||
sl->data[sl_pos] = _PIXPAIR(0, 0x1ff);
|
||||
}
|
||||
|
||||
sl->length = sl_pos;
|
||||
sl->repeat_count = 34;
|
||||
} else if((line >= 48) && (line < 48+128)) {
|
||||
sl->data[sl_pos++] = _PIXPAIR(0x1ff, 0 | THEN_EXTEND_6); // 8px
|
||||
sl->data[sl_pos++] = _PIXPAIR(0 | THEN_EXTEND_1, 0 | THEN_EXTEND_1); // 4px
|
||||
|
||||
const uint z = (line - 48);
|
||||
|
||||
if((z & 0xf) < 14) {
|
||||
const uint g = z / 16;
|
||||
for(uint b=0; b < 3; b++) {
|
||||
for(uint r=0; r < 8; r++) {
|
||||
const uint rgb = (r << 6) | (g << 3) | b;
|
||||
sl->data[sl_pos++] = _PIXPAIR(0, rgb | THEN_EXTEND_6); // 8px
|
||||
sl->data[sl_pos++] = _PIXPAIR(rgb | THEN_EXTEND_6, 0); // 8px
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for(uint i=0; i < 12; i++) {
|
||||
sl->data[sl_pos++] = _PIXPAIR(0 | THEN_EXTEND_15, 0 | THEN_EXTEND_15); // 384px
|
||||
}
|
||||
}
|
||||
|
||||
sl->data[sl_pos++] = _PIXPAIR(0 | THEN_EXTEND_3, 0 | THEN_EXTEND_3); // 8px
|
||||
|
||||
const uint w = (line - 48) << 1;
|
||||
for(uint i=0; i < 32; i+=2) {
|
||||
uint32_t bits_a = char_test_bits(error_message[(w & 0x3E0) | i], (w>>2) & 0x7);
|
||||
uint32_t bits_b = char_test_bits(error_message[(w & 0x3E0) | (i+1)], (w>>2) & 0x7);
|
||||
uint32_t bits = (bits_a << 7) | bits_b;
|
||||
for(uint j=0; j < 7; j++) {
|
||||
uint32_t pixeldata = (bits & 0x2000) ? (0) : (0x1ff);
|
||||
pixeldata |= (bits & 0x1000) ? ((0) << 16) : ((0x1ff) << 16);
|
||||
bits <<= 2;
|
||||
sl->data[sl_pos++] = pixeldata;
|
||||
}
|
||||
}
|
||||
|
||||
sl->data[sl_pos++] = _PIXPAIR(0 | THEN_EXTEND_1, 0 | THEN_EXTEND_1); // 4px
|
||||
sl->data[sl_pos++] = _PIXPAIR(0 | THEN_EXTEND_6, 0x1ff); // 8px
|
||||
|
||||
sl->repeat_count = 1;
|
||||
sl->length = sl_pos;
|
||||
} else if((line >= 176) && (line < 176+128)) {
|
||||
sl->data[sl_pos++] = _PIXPAIR(0x1ff, 0 | THEN_EXTEND_6); // 8px
|
||||
sl->data[sl_pos++] = _PIXPAIR(0 | THEN_EXTEND_1, 0 | THEN_EXTEND_1); // 4px
|
||||
|
||||
const uint z = (line - 176);
|
||||
const uint g = z / 16;
|
||||
|
||||
// center-left square
|
||||
if((z & 0xf) < 14) {
|
||||
uint b = 3;
|
||||
for(uint r=0; r < 8; r++) {
|
||||
const uint rgb = (r << 6) | (g << 3) | b;
|
||||
sl->data[sl_pos++] = _PIXPAIR(0, rgb | THEN_EXTEND_6);
|
||||
sl->data[sl_pos++] = _PIXPAIR(rgb | THEN_EXTEND_6, 0);
|
||||
}
|
||||
} else {
|
||||
for(uint i=0; i < 4; i++) {
|
||||
sl->data[sl_pos++] = _PIXPAIR(0 | THEN_EXTEND_15, 0 | THEN_EXTEND_15);
|
||||
}
|
||||
}
|
||||
|
||||
// center square (logo)
|
||||
for(uint i=0; i < 32; i++) {
|
||||
uint color1 = lores_palette[PicoPalLogo[((z & 0x7e) << 4) | i] >> 4];
|
||||
uint color2 = lores_palette[PicoPalLogo[((z & 0x7e) << 4) | i] & 0xf];
|
||||
sl->data[sl_pos++] = _PIXPAIR(color1 | THEN_EXTEND_1, color2 | THEN_EXTEND_1);
|
||||
}
|
||||
|
||||
// center-right square
|
||||
if((z & 0xf) < 14) {
|
||||
uint b = 4;
|
||||
for(uint r=0; r < 8; r++) {
|
||||
const uint rgb = (r << 6) | (g << 3) | b;
|
||||
sl->data[sl_pos++] = _PIXPAIR(0, rgb | THEN_EXTEND_6);
|
||||
sl->data[sl_pos++] = _PIXPAIR(rgb | THEN_EXTEND_6, 0);
|
||||
}
|
||||
} else {
|
||||
for(uint i=0; i < 4; i++) {
|
||||
sl->data[sl_pos++] = _PIXPAIR(0 | THEN_EXTEND_15, 0 | THEN_EXTEND_15);
|
||||
}
|
||||
}
|
||||
|
||||
sl->data[sl_pos++] = _PIXPAIR(0 | THEN_EXTEND_3, 0 | THEN_EXTEND_3); // 8px
|
||||
|
||||
const uint w = (line - 48) << 1;
|
||||
for(uint i=0; i < 32; i+=2) {
|
||||
uint32_t bits_a = char_test_bits(error_message[(w & 0x3E0) | i], (w>>2) & 0x7);
|
||||
uint32_t bits_b = char_test_bits(error_message[(w & 0x3E0) | (i+1)], (w>>2) & 0x7);
|
||||
uint32_t bits = (bits_a << 7) | bits_b;
|
||||
for(uint j=0; j < 7; j++) {
|
||||
uint32_t pixeldata = (bits & 0x2000) ? (0) : (0x1ff);
|
||||
pixeldata |= (bits & 0x1000) ? ((0) << 16) : ((0x1ff) << 16);
|
||||
bits <<= 2;
|
||||
sl->data[sl_pos++] = pixeldata;
|
||||
}
|
||||
}
|
||||
|
||||
sl->data[sl_pos++] = _PIXPAIR(0 | THEN_EXTEND_1, 0 | THEN_EXTEND_1); // 4px
|
||||
sl->data[sl_pos++] = _PIXPAIR(0 | THEN_EXTEND_6, 0x1ff); // 8px
|
||||
|
||||
sl->repeat_count = 1;
|
||||
sl->length = sl_pos;
|
||||
} else if((line >= 304) && (line < 304+128)) {
|
||||
sl->data[sl_pos++] = _PIXPAIR(0x1ff, 0 | THEN_EXTEND_6); // 8px
|
||||
sl->data[sl_pos++] = _PIXPAIR(0 | THEN_EXTEND_1, 0 | THEN_EXTEND_1); // 4px
|
||||
|
||||
const uint z = (line - 304);
|
||||
|
||||
if((z & 0xf) < 14) {
|
||||
const uint g = z / 16;
|
||||
for(uint b=5; b < 8; b++) {
|
||||
for(uint r=0; r < 8; r++) {
|
||||
const uint rgb = (r << 6) | (g << 3) | b;
|
||||
sl->data[sl_pos++] = _PIXPAIR(0, rgb | THEN_EXTEND_6);
|
||||
sl->data[sl_pos++] = _PIXPAIR(rgb | THEN_EXTEND_6, 0);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for(uint i=0; i < 12; i++) {
|
||||
sl->data[sl_pos++] = _PIXPAIR(0 | THEN_EXTEND_15, 0 | THEN_EXTEND_15); // 384px
|
||||
}
|
||||
}
|
||||
|
||||
sl->data[sl_pos++] = _PIXPAIR(0 | THEN_EXTEND_3, 0 | THEN_EXTEND_3); // 8px
|
||||
|
||||
const uint w = (line - 48) << 1;
|
||||
for(uint i=0; i < 32; i+=2) {
|
||||
uint32_t bits_a = char_test_bits(error_message[(w & 0x3E0) | i], (w>>2) & 0x7);
|
||||
uint32_t bits_b = char_test_bits(error_message[(w & 0x3E0) | (i+1)], (w>>2) & 0x7);
|
||||
uint32_t bits = (bits_a << 7) | bits_b;
|
||||
for(uint j=0; j < 7; j++) {
|
||||
uint32_t pixeldata = (bits & 0x2000) ? (0) : (0x1ff);
|
||||
pixeldata |= (bits & 0x1000) ? ((0) << 16) : ((0x1ff) << 16);
|
||||
bits <<= 2;
|
||||
sl->data[sl_pos++] = pixeldata;
|
||||
}
|
||||
}
|
||||
|
||||
sl->data[sl_pos++] = _PIXPAIR(0 | THEN_EXTEND_1, 0 | THEN_EXTEND_1); // 4px
|
||||
sl->data[sl_pos++] = _PIXPAIR(0 | THEN_EXTEND_6, 0x1ff); // 8px
|
||||
|
||||
sl->repeat_count = 1;
|
||||
sl->length = sl_pos;
|
||||
} else if(line < VGA_HEIGHT) {
|
||||
// black w/ white border
|
||||
sl->data[sl_pos++] = _PIXPAIR(0x1ff, 0 | THEN_EXTEND_6);
|
||||
for(uint i=0; i < 39; i++) {
|
||||
sl->data[sl_pos++] = _PIXPAIR(0 | THEN_EXTEND_7, 0 | THEN_EXTEND_7);
|
||||
}
|
||||
sl->data[sl_pos++] = _PIXPAIR(0 | THEN_EXTEND_6, 0x1ff);
|
||||
|
||||
sl->length = sl_pos;
|
||||
} else {
|
||||
sl->data[sl_pos++] = _PIXPAIR(0, 0);
|
||||
|
||||
sl->length = sl_pos;
|
||||
}
|
||||
|
||||
line += sl->repeat_count + 1;
|
||||
vga_submit_scanline(sl);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DELAYED_COPY_CODE(render_status_line)() {
|
||||
for(uint glyph_line=0; glyph_line < 8; glyph_line++) {
|
||||
struct vga_scanline *sl = vga_prepare_scanline();
|
||||
uint8_t *line_buf = status_line;
|
||||
uint32_t bits;
|
||||
uint sl_pos = 0;
|
||||
|
||||
// Pad 40 pixels on the left to center horizontally
|
||||
sl->data[sl_pos++] = (text_border|THEN_EXTEND_31) | ((text_border|THEN_EXTEND_7) << 16); // 16 pixels per word
|
||||
|
||||
for(uint col=0; col < 40; ) {
|
||||
// Grab 14 pixels from the next two characters
|
||||
if(*line_buf != 0) {
|
||||
bits = char_test_bits(*line_buf++, glyph_line) << 7;
|
||||
} else {
|
||||
bits = 0x7f << 7;
|
||||
}
|
||||
if(*line_buf != 0) {
|
||||
bits |= char_test_bits(*line_buf++, glyph_line);
|
||||
} else {
|
||||
bits |= 0x7f;
|
||||
}
|
||||
col++;
|
||||
|
||||
// Translate each pair of bits into a pair of pixels
|
||||
for(int i=0; i < 7; i++) {
|
||||
uint32_t pixeldata = (bits & 0x2000) ? (0x000) : (0x1ff);
|
||||
pixeldata |= (bits & 0x1000) ?
|
||||
((uint32_t)0x000) << 16 :
|
||||
((uint32_t)0x1ff) << 16;
|
||||
bits <<= 2;
|
||||
|
||||
sl->data[sl_pos] = pixeldata;
|
||||
sl_pos++;
|
||||
}
|
||||
}
|
||||
|
||||
// Pad 40 pixels on the right to center horizontally
|
||||
sl->data[sl_pos++] = (text_border|THEN_EXTEND_31) | ((text_border|THEN_EXTEND_7) << 16); // 16 pixels per word
|
||||
|
||||
sl->length = sl_pos;
|
||||
sl->repeat_count = 1;
|
||||
vga_submit_scanline(sl);
|
||||
}
|
||||
}
|
144
vga/render_text.c
Normal file
144
vga/render_text.c
Normal file
@ -0,0 +1,144 @@
|
||||
#include <pico/stdlib.h>
|
||||
#include "common/config.h"
|
||||
#include "vga/vgabuf.h"
|
||||
#include "vga/render.h"
|
||||
#include "vga/vgaout.h"
|
||||
|
||||
//#define PAGE2SEL (!(soft_switches & SOFTSW_80STORE) && (soft_switches & SOFTSW_PAGE_2))
|
||||
#define PAGE2SEL ((soft_switches & (SOFTSW_80STORE | SOFTSW_PAGE_2)) == SOFTSW_PAGE_2)
|
||||
|
||||
volatile uint_fast32_t text_flasher_mask = 0;
|
||||
static uint64_t next_flash_tick = 0;
|
||||
|
||||
void DELAYED_COPY_CODE(update_text_flasher)() {
|
||||
uint64_t now = time_us_64();
|
||||
if(now > next_flash_tick) {
|
||||
text_flasher_mask ^= 0x7f;
|
||||
|
||||
switch(current_machine) {
|
||||
default:
|
||||
case MACHINE_II:
|
||||
case MACHINE_PRAVETZ:
|
||||
next_flash_tick = now + 125000u;
|
||||
break;
|
||||
case MACHINE_IIE:
|
||||
case MACHINE_IIGS:
|
||||
next_flash_tick = now + 250000u;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static inline uint_fast8_t char_text_bits(uint_fast8_t ch, uint_fast8_t glyph_line) {
|
||||
uint_fast8_t bits, invert;
|
||||
|
||||
if((soft_switches & SOFTSW_ALTCHAR) || (ch & 0x80)) {
|
||||
// normal / mousetext character
|
||||
invert = 0x00;
|
||||
} else {
|
||||
// flashing character or inverse character
|
||||
invert = (ch & 0x40) ? text_flasher_mask : 0x7f;
|
||||
ch = (ch & 0x3f) | 0x80;
|
||||
}
|
||||
|
||||
bits = character_rom[((uint_fast16_t)ch << 3) | glyph_line] & 0x7f;
|
||||
|
||||
return bits ^ invert;
|
||||
}
|
||||
|
||||
void DELAYED_COPY_CODE(render_text)() {
|
||||
for(uint line=0; line < 24; line++) {
|
||||
if(soft_switches & SOFTSW_80COL) {
|
||||
render_text80_line(PAGE2SEL, line);
|
||||
} else {
|
||||
render_text40_line(PAGE2SEL, line);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DELAYED_COPY_CODE(render_text40_line)(bool p2, unsigned int line) {
|
||||
const uint8_t *page = (const uint8_t *)(p2 ? text_p2 : text_p1);
|
||||
const uint8_t *line_buf = (const uint8_t *)(page + ((line & 0x7) << 7) + (((line >> 3) & 0x3) * 40));
|
||||
|
||||
for(uint glyph_line=0; glyph_line < 8; glyph_line++) {
|
||||
struct vga_scanline *sl = vga_prepare_scanline();
|
||||
uint sl_pos = 0;
|
||||
|
||||
// Pad 40 pixels on the left to center horizontally
|
||||
sl->data[sl_pos++] = (text_border|THEN_EXTEND_31) | ((text_border|THEN_EXTEND_7) << 16); // 16 pixels per word
|
||||
|
||||
for(uint col=0; col < 40; ) {
|
||||
// Grab 14 pixels from the next two characters
|
||||
uint32_t bits_a = char_text_bits(line_buf[col], glyph_line);
|
||||
col++;
|
||||
uint32_t bits_b = char_text_bits(line_buf[col], glyph_line);
|
||||
col++;
|
||||
|
||||
uint32_t bits = (bits_a << 7) | bits_b;
|
||||
|
||||
// Translate each pair of bits into a pair of pixels
|
||||
for(int i=0; i < 7; i++) {
|
||||
uint32_t pixeldata = (bits & 0x2000) ? (text_back|THEN_EXTEND_1) : (text_fore|THEN_EXTEND_1);
|
||||
pixeldata |= (bits & 0x1000) ?
|
||||
((uint32_t)text_back|THEN_EXTEND_1) << 16 :
|
||||
((uint32_t)text_fore|THEN_EXTEND_1) << 16;
|
||||
bits <<= 2;
|
||||
|
||||
sl->data[sl_pos] = pixeldata;
|
||||
sl_pos++;
|
||||
}
|
||||
}
|
||||
|
||||
// Pad 40 pixels on the right to center horizontally
|
||||
sl->data[sl_pos++] = (text_border|THEN_EXTEND_31) | ((text_border|THEN_EXTEND_7) << 16); // 16 pixels per word
|
||||
|
||||
sl->length = sl_pos;
|
||||
sl->repeat_count = 1;
|
||||
vga_submit_scanline(sl);
|
||||
}
|
||||
}
|
||||
|
||||
void DELAYED_COPY_CODE(render_text80_line)(bool p2, unsigned int line) {
|
||||
const uint8_t *page_a = (const uint8_t *)(p2 ? text_p2 : text_p1);
|
||||
const uint8_t *page_b = (const uint8_t *)(p2 ? text_p4 : text_p3);
|
||||
const uint8_t *line_buf_a = page_a + ((line & 0x7) << 7) + (((line >> 3) & 0x3) * 40);
|
||||
const uint8_t *line_buf_b = page_b + ((line & 0x7) << 7) + (((line >> 3) & 0x3) * 40);
|
||||
|
||||
for(uint glyph_line=0; glyph_line < 8; glyph_line++) {
|
||||
struct vga_scanline *sl = vga_prepare_scanline();
|
||||
uint sl_pos = 0;
|
||||
|
||||
// Pad 40 pixels on the left to center horizontally
|
||||
sl->data[sl_pos++] = (text_border|THEN_EXTEND_31) | ((text_border|THEN_EXTEND_7) << 16); // 16 pixels per word
|
||||
|
||||
for(uint col=0; col < 40; ) {
|
||||
// Grab 14 pixels from the next two characters
|
||||
uint32_t bits_a = char_text_bits(line_buf_a[col], glyph_line);
|
||||
uint32_t bits_b = char_text_bits(line_buf_b[col], glyph_line);
|
||||
col++;
|
||||
|
||||
uint32_t bits = (bits_b << 7) | bits_a;
|
||||
|
||||
// Translate each pair of bits into a pair of pixels
|
||||
for(int i=0; i < 7; i++) {
|
||||
uint32_t pixeldata = (bits & 0x2000) ? (text_back) : (text_fore);
|
||||
pixeldata |= (bits & 0x1000) ?
|
||||
((uint32_t)text_back) << 16 :
|
||||
((uint32_t)text_fore) << 16;
|
||||
bits <<= 2;
|
||||
|
||||
sl->data[sl_pos] = pixeldata;
|
||||
sl_pos++;
|
||||
}
|
||||
}
|
||||
|
||||
// Pad 40 pixels on the right to center horizontally
|
||||
sl->data[sl_pos++] = (text_border|THEN_EXTEND_31) | ((text_border|THEN_EXTEND_7) << 16); // 16 pixels per word
|
||||
|
||||
sl->length = sl_pos;
|
||||
sl->repeat_count = 1;
|
||||
vga_submit_scanline(sl);
|
||||
}
|
||||
}
|
||||
|
116
vga/vga12.pio
Normal file
116
vga/vga12.pio
Normal file
@ -0,0 +1,116 @@
|
||||
; This program consists of 3 state machines communicating using state machine IRQs
|
||||
; - hsync generates the hsync signal and drives the vsync and data state machines
|
||||
; - vsync generates the vsync signal and drives the data state machine
|
||||
; - data generates the pixel data stream, synchronized with the hsync and vsync IRQs
|
||||
; generated by their respective timing state machine
|
||||
;
|
||||
; Overall timing (in pixel times)
|
||||
;
|
||||
; Time | hsync action | vsync action | data action
|
||||
; ------------------------------------------------------------------------------------------------
|
||||
; 0 | assert lineclk IRQ | |
|
||||
; 8 | | wait & reset lineclk IRQ |
|
||||
; 16 | set hsync signal low | set vsync signal high/low |
|
||||
; 112 | set hsync signal high | |
|
||||
; 144 | | assert vsync IRQ |
|
||||
; 144.5 | | | 'wait irq vsync' completes
|
||||
; 152 | assert hsync IRQ | |
|
||||
; 152.5 | | | 'wait irq hsync' completes
|
||||
; 160 | deassert hsync IRQ | | first pixel RGB data out
|
||||
; 161 | | | second pixel RGB data out
|
||||
; 216 | | deassert vsync IRQ |
|
||||
|
||||
.define LINECLK_IRQ_NUM 4
|
||||
.define HSYNC_IRQ_NUM 5
|
||||
.define VSYNC_IRQ_NUM 6
|
||||
|
||||
|
||||
; Run at 4 * pixel frequency
|
||||
.program vga_data
|
||||
.origin 0
|
||||
|
||||
.wrap_target
|
||||
pixel_out:
|
||||
out PINS, 12
|
||||
out PC, 4
|
||||
public wait_vsync:
|
||||
wait 0 irq VSYNC_IRQ_NUM
|
||||
public wait_hsync:
|
||||
wait 0 irq HSYNC_IRQ_NUM [1]
|
||||
public extend_31: ; 32 pixels / an extra 62 clocks (32+4+12+2+6+4+2)
|
||||
nop [31]
|
||||
public extend_15: ; 16 pixels / an extra 30 clocks (4+12+2+6+4+2)
|
||||
nop [3]
|
||||
public extend_13: ; 14 pixels / an extra 26 clocks (12+2+6+4+2)
|
||||
nop [11]
|
||||
public extend_7: ; 8 pixels / an extra 14 clocks (2+6+4+2)
|
||||
nop [1]
|
||||
public extend_6: ; 7 pixels / an extra 12 clocks (6+4+2)
|
||||
nop [5]
|
||||
public extend_3: ; 4 pixels / an extra 6 clocks (4+2)
|
||||
nop [3]
|
||||
public extend_1: ; 2 pixels / an extra 2 clocks
|
||||
nop [1]
|
||||
.wrap
|
||||
|
||||
|
||||
; Run at pixel frequency / 8
|
||||
.program vga_hsync
|
||||
pull ; load timing loop count from the CPU
|
||||
.wrap_target
|
||||
irq set LINECLK_IRQ_NUM [1] ; (0) assert lineclk IRQ
|
||||
set PINS, 0 [11] ; (16) set hsync signal low
|
||||
set PINS, 1 [4] ; (112) set hsync signal high
|
||||
irq clear HSYNC_IRQ_NUM ; (152) assert hsync IRQ
|
||||
irq set HSYNC_IRQ_NUM ; (160) deassert hsync IRQ
|
||||
|
||||
; Wait until the next hsync should be generated
|
||||
mov X, OSR
|
||||
skip_loop:
|
||||
jmp X--, skip_loop
|
||||
.wrap
|
||||
|
||||
|
||||
; Run at pixel frequency / 8
|
||||
.program vga_vsync
|
||||
pull ; load timing loop count from the CPU
|
||||
.wrap_target
|
||||
wait 1 irq LINECLK_IRQ_NUM ; (8) wait & reset lineclk IRQ
|
||||
set pins, 0 [15] ; (16) set vsync signal low
|
||||
irq clear VSYNC_IRQ_NUM [8] ; (144) assert vsync IRQ
|
||||
irq set VSYNC_IRQ_NUM ; (216) deassert vsync IRQ
|
||||
wait 1 irq LINECLK_IRQ_NUM
|
||||
wait 1 irq LINECLK_IRQ_NUM ; (8) wait for lineclk & reset
|
||||
set pins, 1 ; (16) set vsync signal high
|
||||
|
||||
; Skip the remaining scanlines
|
||||
mov X, OSR
|
||||
skip_loop:
|
||||
wait 1 irq LINECLK_IRQ_NUM
|
||||
jmp X--, skip_loop
|
||||
.wrap
|
||||
|
||||
|
||||
; Pixel Frequency: 25.175MHz
|
||||
;
|
||||
; Horizontal timing
|
||||
;
|
||||
; 640x480@60Hz and 640x400@70Hz (pulse low)
|
||||
; Scanline part | Pixels | Time [µs]
|
||||
; ------------------------------------------
|
||||
; Visible area | 640 | 25.422045680238
|
||||
; Front porch | 16 | 0.63555114200596
|
||||
; Sync pulse | 96 | 3.8133068520357
|
||||
; Back porch | 48 | 1.9066534260179
|
||||
; Whole line | 800 | 31.777557100298
|
||||
;
|
||||
; Vertical timing
|
||||
;
|
||||
; [640x480@60Hz (pulse low)] || [640x400@70Hz (pulse high)]
|
||||
; Frame part | Lines | Time [ms] || Lines | Time [ms]
|
||||
;------------------------------------------------------------------------
|
||||
; Visible area | 480 | 15.253227408143 || 400 | 12.711022840119
|
||||
; Front porch | 10 | 0.31777557100298 || 12 | 0.38133068520357
|
||||
; Sync pulse | 2 | 0.063555114200596 || 2 | 0.063555114200596
|
||||
; Back porch | 33 | 1.0486593843098 || 35 | 1.1122144985104
|
||||
; Whole frame | 525 | 16.683217477656 || 449 | 14.268123138034
|
116
vga/vga9.pio
Normal file
116
vga/vga9.pio
Normal file
@ -0,0 +1,116 @@
|
||||
; This program consists of 3 state machines communicating using state machine IRQs
|
||||
; - hsync generates the hsync signal and drives the vsync and data state machines
|
||||
; - vsync generates the vsync signal and drives the data state machine
|
||||
; - data generates the pixel data stream, synchronized with the hsync and vsync IRQs
|
||||
; generated by their respective timing state machine
|
||||
;
|
||||
; Overall timing (in pixel times)
|
||||
;
|
||||
; Time | hsync action | vsync action | data action
|
||||
; ------------------------------------------------------------------------------------------------
|
||||
; 0 | assert lineclk IRQ | |
|
||||
; 8 | | wait & reset lineclk IRQ |
|
||||
; 16 | set hsync signal low | set vsync signal high/low |
|
||||
; 112 | set hsync signal high | |
|
||||
; 144 | | assert vsync IRQ |
|
||||
; 144.5 | | | 'wait irq vsync' completes
|
||||
; 152 | assert hsync IRQ | |
|
||||
; 152.5 | | | 'wait irq hsync' completes
|
||||
; 160 | deassert hsync IRQ | | first pixel RGB data out
|
||||
; 161 | | | second pixel RGB data out
|
||||
; 216 | | deassert vsync IRQ |
|
||||
|
||||
.define LINECLK_IRQ_NUM 4
|
||||
.define HSYNC_IRQ_NUM 5
|
||||
.define VSYNC_IRQ_NUM 6
|
||||
|
||||
|
||||
; Run at 4 * pixel frequency
|
||||
.program vga_data
|
||||
.origin 0
|
||||
|
||||
.wrap_target
|
||||
pixel_out:
|
||||
out PINS, 9
|
||||
out PC, 7
|
||||
public wait_vsync:
|
||||
wait 0 irq VSYNC_IRQ_NUM
|
||||
public wait_hsync:
|
||||
wait 0 irq HSYNC_IRQ_NUM [1]
|
||||
public extend_31: ;public extend_31: ; 32 pixels / an extra 62 clocks (32+4+12+2+6+4+2)
|
||||
nop [31]
|
||||
public extend_15: ; 16 pixels / an extra 30 clocks (4+12+2+6+4+2)
|
||||
nop [3]
|
||||
public extend_13: ; 14 pixels / an extra 26 clocks (12+2+6+4+2)
|
||||
nop [11]
|
||||
public extend_7: ; 8 pixels / an extra 14 clocks (2+6+4+2)
|
||||
nop [1]
|
||||
public extend_6: ; 7 pixels / an extra 12 clocks (6+4+2)
|
||||
nop [5]
|
||||
public extend_3: ; 4 pixels / an extra 6 clocks (4+2)
|
||||
nop [3]
|
||||
public extend_1: ; 2 pixels / an extra 2 clocks
|
||||
nop [1]
|
||||
.wrap
|
||||
|
||||
|
||||
; Run at pixel frequency / 8
|
||||
.program vga_hsync
|
||||
pull ; load timing loop count from the CPU
|
||||
.wrap_target
|
||||
irq set LINECLK_IRQ_NUM [1] ; (0) assert lineclk IRQ
|
||||
set PINS, 0 [11] ; (16) set hsync signal low
|
||||
set PINS, 1 [4] ; (112) set hsync signal high
|
||||
irq clear HSYNC_IRQ_NUM ; (152) assert hsync IRQ
|
||||
irq set HSYNC_IRQ_NUM ; (160) deassert hsync IRQ
|
||||
|
||||
; Wait until the next hsync should be generated
|
||||
mov X, OSR
|
||||
skip_loop:
|
||||
jmp X--, skip_loop
|
||||
.wrap
|
||||
|
||||
|
||||
; Run at pixel frequency / 8
|
||||
.program vga_vsync
|
||||
pull ; load timing loop count from the CPU
|
||||
.wrap_target
|
||||
wait 1 irq LINECLK_IRQ_NUM ; (8) wait & reset lineclk IRQ
|
||||
set pins, 0 [15] ; (16) set vsync signal low
|
||||
irq clear VSYNC_IRQ_NUM [8] ; (144) assert vsync IRQ
|
||||
irq set VSYNC_IRQ_NUM ; (216) deassert vsync IRQ
|
||||
wait 1 irq LINECLK_IRQ_NUM
|
||||
wait 1 irq LINECLK_IRQ_NUM ; (8) wait for lineclk & reset
|
||||
set pins, 1 ; (16) set vsync signal high
|
||||
|
||||
; Skip the remaining scanlines
|
||||
mov X, OSR
|
||||
skip_loop:
|
||||
wait 1 irq LINECLK_IRQ_NUM
|
||||
jmp X--, skip_loop
|
||||
.wrap
|
||||
|
||||
|
||||
; Pixel Frequency: 25.175MHz
|
||||
;
|
||||
; Horizontal timing
|
||||
;
|
||||
; 640x480@60Hz and 640x400@70Hz (pulse low)
|
||||
; Scanline part | Pixels | Time [µs]
|
||||
; ------------------------------------------
|
||||
; Visible area | 640 | 25.422045680238
|
||||
; Front porch | 16 | 0.63555114200596
|
||||
; Sync pulse | 96 | 3.8133068520357
|
||||
; Back porch | 48 | 1.9066534260179
|
||||
; Whole line | 800 | 31.777557100298
|
||||
;
|
||||
; Vertical timing
|
||||
;
|
||||
; [640x480@60Hz (pulse low)] || [640x400@70Hz (pulse high)]
|
||||
; Frame part | Lines | Time [ms] || Lines | Time [ms]
|
||||
;------------------------------------------------------------------------
|
||||
; Visible area | 480 | 15.253227408143 || 400 | 12.711022840119
|
||||
; Front porch | 10 | 0.31777557100298 || 12 | 0.38133068520357
|
||||
; Sync pulse | 2 | 0.063555114200596 || 2 | 0.063555114200596
|
||||
; Back porch | 33 | 1.0486593843098 || 35 | 1.1122144985104
|
||||
; Whole frame | 525 | 16.683217477656 || 449 | 14.268123138034
|
20
vga/vgabuf.c
Normal file
20
vga/vgabuf.c
Normal file
@ -0,0 +1,20 @@
|
||||
#include "common/config.h"
|
||||
#include "vga/vgabuf.h"
|
||||
|
||||
volatile uint32_t mono_palette = 0;
|
||||
|
||||
// The currently programmed character generator ROM for text mode
|
||||
uint8_t __attribute__((section(".uninitialized_data."))) character_rom[4096];
|
||||
uint8_t __attribute__((section(".uninitialized_data."))) terminal_character_rom[4096];
|
||||
|
||||
volatile uint8_t terminal_row = 0;
|
||||
volatile uint8_t terminal_col = 0;
|
||||
|
||||
volatile uint8_t terminal_tbcolor = 0xF6;
|
||||
volatile uint8_t terminal_border = 0x6;
|
||||
|
||||
volatile uint8_t romx_type = 0;
|
||||
volatile uint8_t romx_unlocked = 0;
|
||||
volatile uint8_t romx_textbank = 0;
|
||||
volatile uint8_t romx_changed = 0;
|
||||
|
34
vga/vgabuf.h
Normal file
34
vga/vgabuf.h
Normal file
@ -0,0 +1,34 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include "common/buffers.h"
|
||||
|
||||
#define text_memory text_p1
|
||||
#define hires_memory hgr_p1
|
||||
#define terminal_memory (private_memory+0xF000)
|
||||
|
||||
extern uint8_t character_rom[4096];
|
||||
extern uint8_t terminal_character_rom[4096];
|
||||
|
||||
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 ((terminal_tbcolor>>4) & 0xf)
|
||||
#define APPLE_BACK (terminal_tbcolor & 0xf)
|
||||
#define APPLE_BORDER (terminal_border & 0xf)
|
||||
|
||||
extern volatile uint32_t mono_palette;
|
||||
extern volatile uint8_t terminal_tbcolor;
|
||||
extern volatile uint8_t terminal_border;
|
||||
|
||||
#define TERMINAL_FORE ((terminal_tbcolor>>4) & 0xf)
|
||||
#define TERMINAL_BACK (terminal_tbcolor & 0xf)
|
||||
#define TERMINAL_BORDER (terminal_border & 0xf)
|
||||
|
||||
extern volatile uint8_t romx_type;
|
||||
extern volatile uint8_t romx_unlocked;
|
||||
extern volatile uint8_t romx_textbank;
|
||||
extern volatile uint8_t romx_changed;
|
16
vga/vgamain.c
Normal file
16
vga/vgamain.c
Normal file
@ -0,0 +1,16 @@
|
||||
#include <pico/stdlib.h>
|
||||
#include <pico/multicore.h>
|
||||
#include "common/config.h"
|
||||
#include "common/abus.h"
|
||||
#include "common/config.h"
|
||||
#include "vga/businterface.h"
|
||||
#include "vga/render.h"
|
||||
#include "vga/vgaout.h"
|
||||
|
||||
|
||||
void DELAYED_COPY_CODE(vgamain)() {
|
||||
vga_init();
|
||||
render_init();
|
||||
render_loop();
|
||||
vga_stop();
|
||||
}
|
259
vga/vgaout.c
Normal file
259
vga/vgaout.c
Normal file
@ -0,0 +1,259 @@
|
||||
#include <hardware/dma.h>
|
||||
#include <hardware/irq.h>
|
||||
#include <hardware/pio.h>
|
||||
#include <hardware/sync.h>
|
||||
#include <hardware/resets.h>
|
||||
#include <pico/stdlib.h>
|
||||
#include <pico/multicore.h>
|
||||
|
||||
#include "common/config.h"
|
||||
#include "common/buffers.h"
|
||||
|
||||
#ifdef ANALOG_GS
|
||||
#include "vga12.pio.h"
|
||||
#else
|
||||
#include "vga9.pio.h"
|
||||
#endif
|
||||
|
||||
#include "vgaout.h"
|
||||
|
||||
|
||||
#define PIXEL_FREQ 25.2/*MHz*/
|
||||
#define PIXELS_PER_LINE 800
|
||||
#define LINES_PER_FRAME 525
|
||||
#define LINES_IN_BACK_PORCH 33
|
||||
|
||||
#define HSYNC_TIMING_VALUE (((PIXELS_PER_LINE) / 8) - 23)
|
||||
#define VSYNC_TIMING_VALUE ((LINES_PER_FRAME) - 4)
|
||||
|
||||
#define NUM_SCANLINE_BUFFERS 32
|
||||
|
||||
static bool vga_initialized = 0;
|
||||
|
||||
enum {
|
||||
VGA_HSYNC_SM = 0,
|
||||
VGA_VSYNC_SM = 1,
|
||||
VGA_DATA_SM = 2,
|
||||
};
|
||||
|
||||
// The scanline flags form a simple state machine:
|
||||
// Initial state (0)
|
||||
// \/ prepare()
|
||||
// BUSY
|
||||
// \/ ready()
|
||||
// BUSY|READY
|
||||
// \/ first DMA started
|
||||
// BUSY|READY|STARTED
|
||||
// \/ last DMA completed
|
||||
// READY|STARTED
|
||||
enum {
|
||||
FLAG_BUSY = 0x01,
|
||||
FLAG_READY = 0x02,
|
||||
FLAG_STARTED = 0x04,
|
||||
};
|
||||
|
||||
|
||||
static uint vga_dma_channel;
|
||||
|
||||
// Scanline queue. Scanlines are filled in from the head and are
|
||||
// sent to the DMA engine from the tail.
|
||||
static uint scanline_queue_head;
|
||||
static uint scanline_queue_tail;
|
||||
static struct vga_scanline scanline_queue[NUM_SCANLINE_BUFFERS];
|
||||
|
||||
|
||||
static void DELAYED_COPY_CODE(vga_hsync_setup)(PIO pio, uint sm) {
|
||||
uint program_offset = pio_add_program(pio, &vga_hsync_program);
|
||||
pio_sm_claim(pio, sm);
|
||||
|
||||
pio_sm_config c = vga_hsync_program_get_default_config(program_offset);
|
||||
sm_config_set_clkdiv(&c, CONFIG_SYSCLOCK * 8 / PIXEL_FREQ); // 1/8 * PIXEL_FREQ
|
||||
|
||||
// Map the state machine's OUT pin group to the sync signal pin
|
||||
sm_config_set_out_pins(&c, CONFIG_PIN_HSYNC, 1);
|
||||
sm_config_set_set_pins(&c, CONFIG_PIN_HSYNC, 1);
|
||||
|
||||
// Configure the pins as outputs & connect to the PIO
|
||||
pio_sm_set_consecutive_pindirs(pio, sm, CONFIG_PIN_HSYNC, 1, true);
|
||||
pio_gpio_init(pio, CONFIG_PIN_HSYNC);
|
||||
|
||||
// Load the configuration and push in the timing loop value
|
||||
pio_sm_init(pio, sm, program_offset, &c);
|
||||
pio_sm_put_blocking(pio, sm, HSYNC_TIMING_VALUE);
|
||||
}
|
||||
|
||||
static void DELAYED_COPY_CODE(vga_vsync_setup)(PIO pio, uint sm) {
|
||||
uint program_offset = pio_add_program(pio, &vga_vsync_program);
|
||||
pio_sm_claim(pio, sm);
|
||||
|
||||
pio_sm_config c = vga_vsync_program_get_default_config(program_offset);
|
||||
sm_config_set_clkdiv(&c, CONFIG_SYSCLOCK * 8 / PIXEL_FREQ); // 1/8 * PIXEL_FREQ
|
||||
|
||||
// Map the state machine's OUT pin group to the sync signal pin
|
||||
sm_config_set_out_pins(&c, CONFIG_PIN_VSYNC, 1);
|
||||
sm_config_set_set_pins(&c, CONFIG_PIN_VSYNC, 1);
|
||||
|
||||
// Configure the pins as outputs & connect to the PIO
|
||||
pio_sm_set_consecutive_pindirs(pio, sm, CONFIG_PIN_VSYNC, 1, true);
|
||||
pio_gpio_init(pio, CONFIG_PIN_VSYNC);
|
||||
|
||||
// Load the configuration and push in the timing loop value
|
||||
pio_sm_init(pio, sm, program_offset, &c);
|
||||
pio_sm_put_blocking(pio, sm, VSYNC_TIMING_VALUE);
|
||||
}
|
||||
|
||||
static void DELAYED_COPY_CODE(vga_data_setup)(PIO pio, uint sm) {
|
||||
uint program_offset = pio_add_program(pio, &vga_data_program);
|
||||
pio_sm_claim(pio, sm);
|
||||
|
||||
pio_sm_config c = vga_data_program_get_default_config(program_offset);
|
||||
sm_config_set_clkdiv(&c, CONFIG_SYSCLOCK / (2*PIXEL_FREQ));
|
||||
|
||||
// Map the state machine's OUT pin group to the data pins
|
||||
sm_config_set_out_pins(&c, CONFIG_PIN_RGB_BASE, 9);
|
||||
sm_config_set_set_pins(&c, CONFIG_PIN_RGB_BASE, 9);
|
||||
|
||||
// Enable autopull every 32 bits (2 x (9 data + 5 jump + 2 pad) bits)
|
||||
sm_config_set_out_shift(&c, true, true, 32);
|
||||
|
||||
// Set join the state machine FIFOs to double the TX fifo size
|
||||
sm_config_set_fifo_join(&c, PIO_FIFO_JOIN_TX);
|
||||
|
||||
// Configure the pins as outputs & connect to the PIO
|
||||
pio_sm_set_consecutive_pindirs(pio, sm, CONFIG_PIN_RGB_BASE, 9, true);
|
||||
for(int i=0; i < 9; i++) {
|
||||
pio_gpio_init(pio, CONFIG_PIN_RGB_BASE+i);
|
||||
}
|
||||
|
||||
// Load the configuration, starting execution at 'wait_vsync'
|
||||
pio_sm_init(pio, sm, program_offset+vga_data_offset_wait_vsync, &c);
|
||||
}
|
||||
|
||||
// Start the DMA operation of the next scanline if it's ready.
|
||||
//
|
||||
// Must be called with the VGA spinlock held
|
||||
static void DELAYED_COPY_CODE(trigger_ready_scanline_dma)() {
|
||||
struct vga_scanline *active_scanline = &scanline_queue[scanline_queue_tail];
|
||||
|
||||
if((active_scanline->_flags & (FLAG_BUSY|FLAG_READY|FLAG_STARTED)) == (FLAG_BUSY|FLAG_READY)) {
|
||||
active_scanline->_flags |= FLAG_STARTED;
|
||||
dma_channel_transfer_from_buffer_now(vga_dma_channel, &(active_scanline->_sync), active_scanline->length + 2);
|
||||
}
|
||||
}
|
||||
|
||||
static void DELAYED_COPY_CODE(vga_dma_irq_handler)() {
|
||||
spin_lock_t *lock = spin_lock_instance(CONFIG_VGA_SPINLOCK_ID);
|
||||
struct vga_scanline *active_scanline = &scanline_queue[scanline_queue_tail];
|
||||
|
||||
// Ack the IRQ
|
||||
dma_hw->ints0 = 1u << vga_dma_channel;
|
||||
|
||||
// Repeat the scanline as specified
|
||||
if(active_scanline->repeat_count) {
|
||||
active_scanline->repeat_count--;
|
||||
dma_channel_transfer_from_buffer_now(vga_dma_channel, &(active_scanline->_sync), active_scanline->length + 2);
|
||||
return;
|
||||
}
|
||||
|
||||
// Mark the scanline done
|
||||
active_scanline->_flags &= ~(uint_fast8_t)FLAG_BUSY;
|
||||
|
||||
const uint32_t irq_status = spin_lock_blocking(lock);
|
||||
scanline_queue_tail = (scanline_queue_tail + 1) & (NUM_SCANLINE_BUFFERS-1);
|
||||
trigger_ready_scanline_dma();
|
||||
spin_unlock(lock, irq_status);
|
||||
}
|
||||
|
||||
|
||||
void DELAYED_COPY_CODE(vga_init)() {
|
||||
if(!vga_initialized) {
|
||||
spin_lock_claim(CONFIG_VGA_SPINLOCK_ID);
|
||||
spin_lock_init(CONFIG_VGA_SPINLOCK_ID);
|
||||
|
||||
// Setup the PIO state machines
|
||||
vga_hsync_setup(CONFIG_VGA_PIO, VGA_HSYNC_SM);
|
||||
vga_vsync_setup(CONFIG_VGA_PIO, VGA_VSYNC_SM);
|
||||
vga_data_setup(CONFIG_VGA_PIO, VGA_DATA_SM);
|
||||
|
||||
// Setup the DMA channel for writing to the data PIO state machine
|
||||
vga_dma_channel = dma_claim_unused_channel(true);
|
||||
dma_channel_config c = dma_channel_get_default_config(vga_dma_channel);
|
||||
channel_config_set_transfer_data_size(&c, DMA_SIZE_32);
|
||||
channel_config_set_dreq(&c, pio_get_dreq(CONFIG_VGA_PIO, VGA_DATA_SM, true));
|
||||
dma_channel_configure(vga_dma_channel, &c, &CONFIG_VGA_PIO->txf[VGA_DATA_SM], NULL, 0, false);
|
||||
|
||||
dma_channel_set_irq0_enabled(vga_dma_channel, true);
|
||||
irq_set_exclusive_handler(DMA_IRQ_0, vga_dma_irq_handler);
|
||||
irq_set_enabled(DMA_IRQ_0, true);
|
||||
|
||||
vga_initialized = 1;
|
||||
}
|
||||
|
||||
// Enable all state machines in sync to ensure their instruction cycles line up
|
||||
pio_enable_sm_mask_in_sync(CONFIG_VGA_PIO, (1 << VGA_HSYNC_SM) | (1 << VGA_VSYNC_SM) | (1 << VGA_DATA_SM));
|
||||
}
|
||||
|
||||
void DELAYED_COPY_CODE(vga_stop)() {
|
||||
pio_set_sm_mask_enabled(CONFIG_VGA_PIO, (1 << VGA_HSYNC_SM) | (1 << VGA_VSYNC_SM) | (1 << VGA_DATA_SM), false);
|
||||
}
|
||||
|
||||
void DELAYED_COPY_CODE(vga_dpms_sleep)() {
|
||||
pio_set_sm_mask_enabled(CONFIG_VGA_PIO, (1 << VGA_HSYNC_SM) | (1 << VGA_VSYNC_SM) | (1 << VGA_DATA_SM), false);
|
||||
irq_set_enabled(DMA_IRQ_0, false);
|
||||
dma_channel_set_irq0_enabled(vga_dma_channel, false);
|
||||
}
|
||||
|
||||
void DELAYED_COPY_CODE(vga_dpms_wake)() {
|
||||
dma_channel_set_irq0_enabled(vga_dma_channel, true);
|
||||
irq_set_enabled(DMA_IRQ_0, true);
|
||||
pio_enable_sm_mask_in_sync(CONFIG_VGA_PIO, (1 << VGA_HSYNC_SM) | (1 << VGA_VSYNC_SM) | (1 << VGA_DATA_SM));
|
||||
}
|
||||
|
||||
// Set up for a new display frame
|
||||
void DELAYED_COPY_CODE(vga_prepare_frame)() {
|
||||
// Populate a 'scanline' with multiple sync instructions to synchronize with the
|
||||
// vsync and then skip over the vertical back porch.
|
||||
struct vga_scanline *sl = vga_prepare_scanline();
|
||||
|
||||
sl->_sync = (uint32_t)THEN_WAIT_VSYNC << 16;
|
||||
// FIXME: the number of hsyncs we have to wait for seems to be one too few
|
||||
// because the vsync is supposed to last two lines (we wait one) and THEN
|
||||
// the back porch lines need to be skipped.
|
||||
for(int i=0; i < LINES_IN_BACK_PORCH; i++) {
|
||||
sl->data[i] = (uint32_t)THEN_WAIT_HSYNC << 16;
|
||||
}
|
||||
sl->length = LINES_IN_BACK_PORCH;
|
||||
|
||||
vga_submit_scanline(sl);
|
||||
}
|
||||
|
||||
// Set up and return a new display scanline
|
||||
struct vga_scanline * DELAYED_COPY_CODE(vga_prepare_scanline)() {
|
||||
struct vga_scanline *scanline = &scanline_queue[scanline_queue_head];
|
||||
|
||||
// Wait for the scanline buffer to become available again
|
||||
while(scanline->_flags & FLAG_BUSY)
|
||||
tight_loop_contents();
|
||||
|
||||
// Reinitialize the scanline struct for reuse
|
||||
scanline->length = 0;
|
||||
scanline->repeat_count = 0;
|
||||
scanline->_flags = FLAG_BUSY;
|
||||
scanline->_sync = (uint32_t)THEN_WAIT_HSYNC << 16;
|
||||
|
||||
scanline_queue_head = (scanline_queue_head + 1) & (NUM_SCANLINE_BUFFERS-1);
|
||||
|
||||
return scanline;
|
||||
}
|
||||
|
||||
// Mark the scanline as ready so it can be displayed
|
||||
void DELAYED_COPY_CODE(vga_submit_scanline)(struct vga_scanline *scanline) {
|
||||
spin_lock_t *lock = spin_lock_instance(CONFIG_VGA_SPINLOCK_ID);
|
||||
|
||||
scanline->data[scanline->length] = 0; // ensure beam off at end of line
|
||||
|
||||
const uint32_t irq_status = spin_lock_blocking(lock);
|
||||
scanline->_flags |= FLAG_READY;
|
||||
trigger_ready_scanline_dma();
|
||||
spin_unlock(lock, irq_status);
|
||||
}
|
50
vga/vgaout.h
Normal file
50
vga/vgaout.h
Normal file
@ -0,0 +1,50 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
|
||||
#define VGA_WIDTH 640
|
||||
#define VGA_HEIGHT 480
|
||||
|
||||
#ifdef ANALOG_GS
|
||||
#define THEN_WAIT_VSYNC (2 << 12)
|
||||
#define THEN_WAIT_HSYNC (3 << 12)
|
||||
#define THEN_EXTEND_31 (4 << 12)
|
||||
#define THEN_EXTEND_15 (5 << 12)
|
||||
#define THEN_EXTEND_13 (6 << 12)
|
||||
#define THEN_EXTEND_7 (7 << 12)
|
||||
#define THEN_EXTEND_6 (8 << 12)
|
||||
#define THEN_EXTEND_3 (9 << 12)
|
||||
#define THEN_EXTEND_1 (10 << 12)
|
||||
#else
|
||||
#define THEN_WAIT_VSYNC (2 << 9)
|
||||
#define THEN_WAIT_HSYNC (3 << 9)
|
||||
#define THEN_EXTEND_31 (4 << 9)
|
||||
#define THEN_EXTEND_15 (5 << 9)
|
||||
#define THEN_EXTEND_13 (6 << 9)
|
||||
#define THEN_EXTEND_7 (7 << 9)
|
||||
#define THEN_EXTEND_6 (8 << 9)
|
||||
#define THEN_EXTEND_3 (9 << 9)
|
||||
#define THEN_EXTEND_1 (10 << 9)
|
||||
#endif
|
||||
|
||||
struct vga_scanline {
|
||||
// number of 32-bit words in the data array
|
||||
uint_fast16_t length;
|
||||
|
||||
// number of times to repeat the scanline
|
||||
uint_fast16_t repeat_count;
|
||||
|
||||
volatile uint_fast8_t _flags;
|
||||
|
||||
uint32_t _sync;
|
||||
uint32_t data[(VGA_WIDTH/2)+8];
|
||||
};
|
||||
|
||||
void vga_prepare_frame();
|
||||
struct vga_scanline *vga_prepare_scanline();
|
||||
void vga_submit_scanline(struct vga_scanline *scanline);
|
||||
|
||||
void vga_stop();
|
||||
void vga_dpms_sleep();
|
||||
void vga_dpms_wake();
|
72
z80/businterface.c
Normal file
72
z80/businterface.c
Normal file
@ -0,0 +1,72 @@
|
||||
#include <string.h>
|
||||
#include <hardware/pio.h>
|
||||
#include "common/config.h"
|
||||
#include "common/buffers.h"
|
||||
#include "common/abus.h"
|
||||
#include "z80/businterface.h"
|
||||
#include "z80/z80buf.h"
|
||||
|
||||
volatile uint8_t *pcpi_reg = apple_memory + 0xC0C0;
|
||||
|
||||
static inline void __time_critical_func(pcpi_read)(uint32_t address) {
|
||||
switch(address & 0x7) {
|
||||
case 0: // Read Data from Z80
|
||||
clr_6502_stat;
|
||||
break;
|
||||
case 5: // Z80 Reset
|
||||
z80_res = 1;
|
||||
break;
|
||||
case 6: // Z80 INT
|
||||
//z80_irq = 1;
|
||||
break;
|
||||
case 7: // Z80 NMI
|
||||
z80_nmi = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static inline void __time_critical_func(pcpi_write)(uint32_t address, uint32_t value) {
|
||||
switch(address & 0x7) {
|
||||
case 0:
|
||||
case 2:
|
||||
case 3:
|
||||
case 4:
|
||||
break;
|
||||
case 1: // Write Data to Z80
|
||||
pcpi_reg[1] = value & 0xff;
|
||||
set_z80_stat;
|
||||
break;
|
||||
case 5:
|
||||
case 6:
|
||||
case 7:
|
||||
pcpi_read(address);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void __time_critical_func(z80_businterface)(uint32_t address, uint32_t value) {
|
||||
volatile uint8_t *new_pcpi_reg;
|
||||
|
||||
// Reset the Z80 when the Apple II resets
|
||||
if(reset_state == 3) z80_res = 1;
|
||||
|
||||
// Shadow parts of the Apple's memory by observing the bus write cycles
|
||||
if(CARD_SELECT) {
|
||||
if(CARD_DEVSEL) {
|
||||
// Ideally this code should only run once.
|
||||
new_pcpi_reg = apple_memory + (address & 0xFFF0);
|
||||
if((uint32_t)new_pcpi_reg != (uint32_t)pcpi_reg) {
|
||||
memcpy(new_pcpi_reg, pcpi_reg, 16);
|
||||
pcpi_reg = new_pcpi_reg;
|
||||
}
|
||||
|
||||
if((value & (1u << CONFIG_PIN_APPLEBUS_RW-CONFIG_PIN_APPLEBUS_DATA_BASE)) == 0) {
|
||||
pcpi_write(address, value);
|
||||
} else {
|
||||
pcpi_read(address);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
3
z80/businterface.h
Normal file
3
z80/businterface.h
Normal file
@ -0,0 +1,3 @@
|
||||
#pragma once
|
||||
|
||||
void z80_businterface();
|
21
z80/z80buf.h
Normal file
21
z80/z80buf.h
Normal file
@ -0,0 +1,21 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include "common/buffers.h"
|
||||
|
||||
extern volatile uint32_t z80_vect;
|
||||
extern volatile uint8_t z80_irq;
|
||||
extern volatile uint8_t z80_nmi;
|
||||
extern volatile uint8_t z80_res;
|
||||
extern uint8_t z80_rom[2*1024];
|
||||
#define z80_ram private_memory
|
||||
extern volatile uint8_t *pcpi_reg;
|
||||
|
||||
#define clr_z80_stat { pcpi_reg[2] &= ~0x80; }
|
||||
#define set_z80_stat { pcpi_reg[2] |= 0x80; }
|
||||
#define rd_z80_stat (pcpi_reg[2] >> 7)
|
||||
|
||||
#define clr_6502_stat { pcpi_reg[3] &= ~0x80; }
|
||||
#define set_6502_stat { pcpi_reg[3] |= 0x80; }
|
||||
#define rd_6502_stat (pcpi_reg[3] >> 7)
|
||||
|
4639
z80/z80cpu.h
Normal file
4639
z80/z80cpu.h
Normal file
File diff suppressed because it is too large
Load Diff
121
z80/z80main.c
Normal file
121
z80/z80main.c
Normal file
@ -0,0 +1,121 @@
|
||||
#include <pico/stdlib.h>
|
||||
#include <pico/multicore.h>
|
||||
#include "common/config.h"
|
||||
#include "z80/businterface.h"
|
||||
#include "z80/z80buf.h"
|
||||
#include "z80/z80rom.h"
|
||||
|
||||
volatile uint32_t z80_vect = 0x000000;
|
||||
volatile uint8_t __attribute__((section(".uninitialized_data."))) z80_irq;
|
||||
volatile uint8_t __attribute__((section(".uninitialized_data."))) z80_nmi;
|
||||
volatile uint8_t __attribute__((section(".uninitialized_data."))) z80_res;
|
||||
volatile uint8_t __attribute__((section(".uninitialized_data."))) rom_shadow;
|
||||
volatile uint8_t __attribute__((section(".uninitialized_data."))) ram_bank;
|
||||
volatile uint8_t __attribute__((section(".uninitialized_data."))) ram_common;
|
||||
|
||||
#define Z80break (z80_res || (config_cmdbuf[7] == 0))
|
||||
|
||||
uint8_t DELAYED_COPY_CODE(cpu_in)(uint16_t address) {
|
||||
uint8_t rv = 0;
|
||||
switch(address & 0xe0) {
|
||||
case 0x00: // Write Data to 6502
|
||||
rv = pcpi_reg[0];
|
||||
break;
|
||||
case 0x20: // Read Data from 6502
|
||||
clr_z80_stat;
|
||||
rv = pcpi_reg[1];
|
||||
//printf("I%01X:%02X\r\n", (address >> 4), rv);
|
||||
break;
|
||||
case 0x40: // Status Port
|
||||
if(rd_z80_stat)
|
||||
rv |= 0x80;
|
||||
if(rd_6502_stat)
|
||||
rv |= 0x01;
|
||||
break;
|
||||
case 0x60:
|
||||
break;
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
void DELAYED_COPY_CODE(cpu_out)(uint16_t address, uint8_t value) {
|
||||
switch(address & 0xe0) {
|
||||
case 0x00: // Write Data to 6502
|
||||
//printf("O%01X:%02X\r\n", (address >> 4), value);
|
||||
pcpi_reg[0] = value;
|
||||
set_6502_stat;
|
||||
break;
|
||||
case 0x60:
|
||||
rom_shadow = (value & 1);
|
||||
break;
|
||||
case 0xC0:
|
||||
ram_bank = (value >> 1) & 7;
|
||||
ram_common = (value >> 6) & 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t DELAYED_COPY_CODE(_RamRead)(uint16_t address) {
|
||||
if((rom_shadow & 1) && (address < 0x8000))
|
||||
return z80_rom[address & 0x7ff];
|
||||
|
||||
if((address > 0xE000) && (ram_common)) {
|
||||
return z80_ram[address];
|
||||
}
|
||||
|
||||
if(ram_bank) {
|
||||
return 0xff;
|
||||
}
|
||||
|
||||
return z80_ram[address];
|
||||
}
|
||||
|
||||
void DELAYED_COPY_CODE(_RamWrite)(uint16_t address, uint8_t value) {
|
||||
if((rom_shadow & 1) && (address < 0x8000))
|
||||
return;
|
||||
|
||||
if((address > 0xE000) && (ram_common)) {
|
||||
z80_ram[address] = value;
|
||||
return;
|
||||
}
|
||||
|
||||
if(ram_bank) {
|
||||
return;
|
||||
}
|
||||
|
||||
z80_ram[address] = value;
|
||||
}
|
||||
|
||||
#include "z80cpu.h"
|
||||
|
||||
void DELAYED_COPY_CODE(z80main)() {
|
||||
z80_res = 1;
|
||||
|
||||
for(;;) {
|
||||
if(config_cmdbuf[7] == 0) {
|
||||
config_handler();
|
||||
} else
|
||||
if(cardslot != 0) {
|
||||
if(z80_res) {
|
||||
rom_shadow = 1;
|
||||
ram_bank = 0;
|
||||
ram_common = 0;
|
||||
|
||||
z80_nmi = 0;
|
||||
z80_irq = 0;
|
||||
z80_res = 0;
|
||||
|
||||
// 6502 -> Z80
|
||||
clr_z80_stat;
|
||||
|
||||
// Z80 -> 6502
|
||||
clr_6502_stat;
|
||||
|
||||
Z80reset();
|
||||
}
|
||||
|
||||
Z80run();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
130
z80/z80rom.h
Normal file
130
z80/z80rom.h
Normal file
@ -0,0 +1,130 @@
|
||||
uint8_t z80_rom[2*1024] = {
|
||||
0x18, 0x71, 0x5a, 0x38, 0x30, 0x09, 0x4a, 0x25, 0x00, 0x00, 0x21, 0x00, 0x10, 0x0e, 0x01, 0x18,
|
||||
0x02, 0x0e, 0x02, 0xe5, 0xdd, 0xe1, 0x11, 0xe0, 0x00, 0xdd, 0x19, 0xdd, 0xe9, 0x00, 0x2a, 0x2a,
|
||||
0x20, 0x43, 0x6f, 0x70, 0x79, 0x72, 0x69, 0x67, 0x68, 0x74, 0x20, 0x28, 0x63, 0x29, 0x20, 0x31,
|
||||
0x39, 0x38, 0x32, 0x20, 0x50, 0x65, 0x72, 0x73, 0x6f, 0x6e, 0x6e, 0x65, 0x6c, 0x20, 0x43, 0x6f,
|
||||
0x6d, 0x70, 0x75, 0x74, 0x65, 0x72, 0x20, 0x50, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x73, 0x2c,
|
||||
0x20, 0x49, 0x6e, 0x63, 0x2e, 0x20, 0x20, 0x2a, 0x2a, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0xf9, 0xff, 0x3e, 0x02, 0xf5, 0x21, 0xd3, 0x00, 0xe5,
|
||||
0xfb, 0xed, 0x45, 0x3e, 0x01, 0x18, 0x39, 0x3e, 0x3e, 0x20, 0x57, 0x69, 0x6e, 0x74, 0x68, 0x72,
|
||||
0x6f, 0x70, 0x20, 0x4c, 0x2e, 0x20, 0x53, 0x61, 0x76, 0x69, 0x6c, 0x6c, 0x65, 0x20, 0x49, 0x49,
|
||||
0x49, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x52, 0x61, 0x79, 0x6d, 0x6f, 0x6e, 0x64, 0x20, 0x4b, 0x6c,
|
||||
0x65, 0x69, 0x6e, 0x20, 0x2d, 0x20, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x73, 0x20, 0x3c, 0x3c,
|
||||
0x06, 0x1f, 0x0e, 0xdf, 0xed, 0x41, 0x0d, 0x10, 0xfb, 0xed, 0x41, 0x31, 0xf9, 0xff, 0xf5, 0x3e,
|
||||
0x7a, 0xd3, 0x00, 0x2a, 0xfe, 0xff, 0x11, 0xab, 0x55, 0x19, 0x7c, 0xb5, 0xc2, 0xd3, 0x00, 0xf1,
|
||||
0xc3, 0x6c, 0x02, 0x3e, 0x31, 0xd3, 0x00, 0x3e, 0x32, 0xd3, 0x00, 0x21, 0x00, 0x00, 0x0e, 0x03,
|
||||
0x11, 0xff, 0x07, 0x06, 0x00, 0x78, 0x86, 0x47, 0x23, 0x1b, 0x7a, 0xb3, 0x20, 0xf7, 0x70, 0x7e,
|
||||
0xb8, 0xf5, 0x79, 0xfe, 0x03, 0x28, 0x05, 0xe1, 0xfe, 0x02, 0xc8, 0xff, 0xf1, 0x28, 0x07, 0x3a,
|
||||
0x1d, 0x00, 0xb7, 0xca, 0xae, 0x01, 0xf1, 0xfe, 0x01, 0xca, 0x6c, 0x02, 0x3e, 0x33, 0xd3, 0x00,
|
||||
0x21, 0x00, 0x00, 0x11, 0x00, 0x80, 0x01, 0x00, 0x08, 0xed, 0xb0, 0xc3, 0x1e, 0x81, 0x3e, 0x00,
|
||||
0xd3, 0x60, 0x0e, 0x00, 0x21, 0x00, 0x00, 0x11, 0x00, 0x80, 0x06, 0x43, 0x79, 0x80, 0x4f, 0x70,
|
||||
0x04, 0x23, 0x1b, 0x7b, 0xb2, 0x20, 0xf5, 0x21, 0x00, 0x80, 0x11, 0x00, 0x08, 0x79, 0x86, 0x4f,
|
||||
0x23, 0x1b, 0x7b, 0xb2, 0x20, 0xf7, 0x06, 0x43, 0x79, 0x80, 0x4f, 0x70, 0x04, 0x23, 0x7c, 0xb5,
|
||||
0x20, 0xf6, 0x21, 0x00, 0x80, 0x2b, 0x7c, 0xb5, 0x20, 0xfb, 0x21, 0x00, 0x00, 0x06, 0x00, 0x78,
|
||||
0x86, 0x47, 0x23, 0x7c, 0xb5, 0x20, 0xf8, 0x78, 0xb9, 0x20, 0x43, 0x3e, 0x34, 0xd3, 0x00, 0xc3,
|
||||
0x72, 0x81, 0x3e, 0x00, 0xd3, 0x60, 0x21, 0x00, 0x00, 0xcd, 0xb9, 0x81, 0x21, 0x00, 0x80, 0x11,
|
||||
0x00, 0x00, 0x01, 0x00, 0x08, 0xed, 0xb0, 0x21, 0x00, 0x00, 0x06, 0x00, 0x11, 0xff, 0x07, 0x78,
|
||||
0x86, 0x47, 0x23, 0x1b, 0x7a, 0xb3, 0x20, 0xf7, 0x78, 0xbe, 0x20, 0x12, 0xc3, 0x9f, 0x01, 0x31,
|
||||
0xf9, 0x7f, 0x21, 0x00, 0x80, 0xcd, 0xb9, 0x01, 0x31, 0xf9, 0xff, 0xc3, 0xe4, 0x01, 0xf3, 0x21,
|
||||
0xff, 0xff, 0xdb, 0xe0, 0x7e, 0x00, 0x77, 0x18, 0xf9, 0x11, 0x00, 0x80, 0x3e, 0x55, 0x77, 0xbe,
|
||||
0x20, 0xec, 0x3e, 0xaa, 0x77, 0xbe, 0x20, 0xe6, 0x3e, 0xff, 0x77, 0xbe, 0x20, 0xe0, 0x3e, 0x00,
|
||||
0x77, 0xbe, 0x20, 0xda, 0x3e, 0x01, 0x77, 0xbe, 0x20, 0xd4, 0x07, 0x30, 0xf9, 0x23, 0x1b, 0x7a,
|
||||
0xb3, 0x20, 0xd9, 0xc9, 0x3e, 0x35, 0xd3, 0x00, 0x3e, 0x00, 0xd3, 0x80, 0x3e, 0x27, 0xd3, 0x80,
|
||||
0x3e, 0xff, 0xd3, 0x80, 0x06, 0x00, 0xdb, 0x80, 0xfe, 0xfd, 0xca, 0x07, 0x02, 0x00, 0x00, 0x00,
|
||||
0x04, 0xc2, 0xf6, 0x01, 0xc3, 0x61, 0x02, 0x06, 0x00, 0xdb, 0x80, 0xfe, 0xfd, 0xca, 0x18, 0x02,
|
||||
0xfe, 0xfc, 0xca, 0x1f, 0x02, 0xc3, 0x61, 0x02, 0x04, 0xc2, 0x09, 0x02, 0xc3, 0x61, 0x02, 0x3e,
|
||||
0x36, 0xd3, 0x00, 0xed, 0x5e, 0x3e, 0x90, 0xed, 0x47, 0x21, 0x00, 0x90, 0x36, 0xae, 0x2c, 0x36,
|
||||
0x01, 0x2c, 0xc2, 0x2c, 0x02, 0x21, 0x68, 0x02, 0x22, 0x02, 0x90, 0x11, 0x00, 0x00, 0x3e, 0x87,
|
||||
0xd3, 0x81, 0x3e, 0x80, 0xd3, 0x81, 0xfb, 0x21, 0x14, 0x05, 0x2b, 0x7c, 0xb5, 0xc2, 0x4a, 0x02,
|
||||
0xf3, 0x3e, 0x07, 0xd3, 0x81, 0x3e, 0x00, 0xd3, 0x81, 0x21, 0x0a, 0x00, 0xed, 0x52, 0xf2, 0xae,
|
||||
0x01, 0x3e, 0x01, 0xd3, 0x60, 0xc3, 0x6c, 0x02, 0x13, 0xfb, 0xed, 0x4d, 0x21, 0x55, 0xaa, 0x22,
|
||||
0xfe, 0xff, 0x3e, 0x5a, 0xd3, 0x00, 0x11, 0xa0, 0x00, 0x21, 0x00, 0x00, 0xdb, 0x40, 0x17, 0x38,
|
||||
0x0d, 0x2b, 0x7c, 0xb5, 0x20, 0xf6, 0x1b, 0x7a, 0xb3, 0x20, 0xee, 0xc3, 0xef, 0x03, 0xdb, 0x20,
|
||||
0xfe, 0x06, 0x30, 0x12, 0x6f, 0x26, 0x00, 0x29, 0x11, 0xb0, 0x02, 0x19, 0xcd, 0xa1, 0x02, 0x18,
|
||||
0xd5, 0x7e, 0x23, 0x66, 0x6f, 0xe9, 0xfe, 0xf0, 0x20, 0xcc, 0xcd, 0x06, 0x03, 0xc3, 0x76, 0x02,
|
||||
0xbc, 0x02, 0xc9, 0x02, 0xdb, 0x02, 0xed, 0x02, 0xf2, 0x02, 0xfc, 0x02, 0x21, 0x02, 0x00, 0x06,
|
||||
0x08, 0x4e, 0xcd, 0xe5, 0x03, 0x23, 0x10, 0xf9, 0xc9, 0xcd, 0xc8, 0x03, 0xeb, 0xcd, 0xc8, 0x03,
|
||||
0x7a, 0xb3, 0xc8, 0x4e, 0xcd, 0xe5, 0x03, 0x23, 0x1b, 0x18, 0xf5, 0xcd, 0xc8, 0x03, 0xeb, 0xcd,
|
||||
0xc8, 0x03, 0x7a, 0xb3, 0xc8, 0xcd, 0xdc, 0x03, 0x77, 0x23, 0x1b, 0x18, 0xf5, 0xcd, 0xc8, 0x03,
|
||||
0xeb, 0xe9, 0xcd, 0xdc, 0x03, 0x4f, 0xcd, 0xdc, 0x03, 0xed, 0x79, 0xc9, 0xcd, 0xdc, 0x03, 0x4f,
|
||||
0xed, 0x48, 0xcd, 0xe5, 0x03, 0xc9, 0xcd, 0xc8, 0x03, 0xed, 0x53, 0xfd, 0xff, 0xcd, 0xc8, 0x03,
|
||||
0xed, 0x53, 0xfb, 0xff, 0x7b, 0xb2, 0xca, 0x75, 0x03, 0x2a, 0xfd, 0xff, 0xed, 0x4b, 0xfb, 0xff,
|
||||
0x3e, 0x55, 0xcd, 0x7b, 0x03, 0x2a, 0xfd, 0xff, 0xed, 0x4b, 0xfb, 0xff, 0x3e, 0x55, 0xcd, 0x8a,
|
||||
0x03, 0xd8, 0x2a, 0xfd, 0xff, 0xed, 0x4b, 0xfb, 0xff, 0x3e, 0xaa, 0xcd, 0x7b, 0x03, 0x2a, 0xfd,
|
||||
0xff, 0xed, 0x4b, 0xfb, 0xff, 0x3e, 0xaa, 0xcd, 0x8a, 0x03, 0xd8, 0x2a, 0xfd, 0xff, 0xed, 0x4b,
|
||||
0xfb, 0xff, 0x75, 0x23, 0x0b, 0x78, 0xb1, 0x20, 0xf9, 0x2a, 0xfd, 0xff, 0xed, 0x4b, 0xfb, 0xff,
|
||||
0x7e, 0xbd, 0x20, 0x08, 0x23, 0x0b, 0x78, 0xb1, 0x20, 0xf6, 0x18, 0x09, 0x57, 0x5d, 0xcd, 0xa1,
|
||||
0x03, 0x23, 0x30, 0xec, 0xd8, 0x0e, 0x00, 0xcd, 0xe5, 0x03, 0xc9, 0x5f, 0x78, 0xb1, 0xc8, 0x73,
|
||||
0x0b, 0x78, 0xb1, 0xc8, 0x54, 0x5d, 0x13, 0xed, 0xb0, 0xc9, 0x5f, 0x78, 0xb1, 0xc8, 0x7e, 0xbb,
|
||||
0x20, 0x07, 0x23, 0x0b, 0x78, 0xb1, 0x20, 0xf6, 0xc9, 0x57, 0xcd, 0xa1, 0x03, 0x23, 0x30, 0xee,
|
||||
0xc9, 0xe5, 0xd5, 0xc5, 0x0e, 0x01, 0x7e, 0xbb, 0x20, 0x02, 0x0e, 0x02, 0xcd, 0xe5, 0x03, 0xeb,
|
||||
0xcd, 0xd1, 0x03, 0x4d, 0xcd, 0xe5, 0x03, 0x4c, 0xcd, 0xe5, 0x03, 0xcd, 0xdc, 0x03, 0xfe, 0x00,
|
||||
0x37, 0x20, 0x01, 0x3f, 0xc1, 0xd1, 0xe1, 0xc9, 0xcd, 0xdc, 0x03, 0x5f, 0xcd, 0xdc, 0x03, 0x57,
|
||||
0xc9, 0xc5, 0x4b, 0xcd, 0xe5, 0x03, 0x4a, 0xcd, 0xe5, 0x03, 0xc1, 0xc9, 0xdb, 0x40, 0x17, 0xd2,
|
||||
0xdc, 0x03, 0xdb, 0x20, 0xc9, 0xdb, 0x40, 0x1f, 0xda, 0xe5, 0x03, 0x79, 0xd3, 0x00, 0xc9, 0x3e,
|
||||
0x42, 0xd3, 0x00, 0x31, 0xff, 0xef, 0xcd, 0x77, 0x04, 0x32, 0xff, 0xff, 0x21, 0x00, 0x00, 0x11,
|
||||
0x00, 0x80, 0x01, 0x1f, 0x05, 0xed, 0xb0, 0xc3, 0x0a, 0x84, 0x3e, 0x00, 0xd3, 0x60, 0x21, 0x00,
|
||||
0x80, 0x11, 0x00, 0x00, 0x01, 0x1f, 0x05, 0xed, 0xb0, 0xc3, 0x1c, 0x04, 0xcd, 0x77, 0x04, 0x21,
|
||||
0xff, 0xff, 0xbe, 0xc4, 0x6d, 0x04, 0x32, 0x21, 0x05, 0x31, 0x41, 0x05, 0x21, 0x20, 0x05, 0x36,
|
||||
0x55, 0x2b, 0x36, 0x01, 0x08, 0xaf, 0x08, 0xcd, 0x03, 0x05, 0xcd, 0x8e, 0x04, 0xcd, 0x77, 0x04,
|
||||
0x21, 0x21, 0x05, 0xbe, 0xc4, 0x6d, 0x04, 0x21, 0x20, 0x05, 0x46, 0x21, 0x00, 0x06, 0x11, 0x00,
|
||||
0xfa, 0x7e, 0xb8, 0xc4, 0x6d, 0x04, 0x23, 0x1b, 0x7a, 0xb3, 0x20, 0xf5, 0x21, 0x1f, 0x05, 0x34,
|
||||
0x7e, 0xe6, 0x02, 0x20, 0xd2, 0x21, 0x20, 0x05, 0x7e, 0x2f, 0x77, 0x18, 0xca, 0x21, 0xff, 0xff,
|
||||
0xdb, 0xe0, 0x7e, 0x00, 0x77, 0x18, 0xf9, 0x21, 0x00, 0x00, 0x11, 0x1f, 0x05, 0x06, 0x00, 0x7e,
|
||||
0x77, 0x80, 0x47, 0x23, 0x1b, 0x7a, 0xb3, 0x20, 0xf6, 0x78, 0xb7, 0xc0, 0x2f, 0xc9, 0x21, 0x00,
|
||||
0x06, 0x11, 0x00, 0xfa, 0x3a, 0x20, 0x05, 0x47, 0x70, 0x23, 0x1b, 0x7a, 0xb3, 0xc2, 0x98, 0x04,
|
||||
0x21, 0x00, 0x06, 0x4c, 0x3e, 0xfa, 0xf5, 0xdb, 0xe0, 0x2e, 0x00, 0x61, 0x3a, 0x1f, 0x05, 0x47,
|
||||
0x70, 0x04, 0x2c, 0xc2, 0xb0, 0x04, 0xcd, 0x03, 0x05, 0xcd, 0xf9, 0x04, 0xcd, 0x03, 0x05, 0xcd,
|
||||
0xf9, 0x04, 0x21, 0x00, 0x06, 0x11, 0x00, 0xfa, 0x7c, 0xb9, 0x28, 0x0a, 0x3a, 0x20, 0x05, 0xbe,
|
||||
0xc4, 0x6d, 0x04, 0xc3, 0xdc, 0x04, 0x7e, 0xb8, 0xc4, 0x6d, 0x04, 0x04, 0x23, 0x1b, 0x7a, 0xb3,
|
||||
0xc2, 0xc8, 0x04, 0xcd, 0x03, 0x05, 0x2e, 0x00, 0x61, 0x3a, 0x20, 0x05, 0x77, 0x2c, 0xc2, 0xec,
|
||||
0x04, 0x0c, 0xf1, 0x3d, 0xf5, 0x20, 0xb0, 0xf1, 0xc9, 0x21, 0x00, 0x0b, 0x2b, 0x7c, 0xb5, 0xc2,
|
||||
0xfc, 0x04, 0xc9, 0xf5, 0xc5, 0x08, 0x4f, 0x3c, 0x08, 0x06, 0x80, 0x79, 0xd3, 0x00, 0x3e, 0x01,
|
||||
0xd3, 0x60, 0x3e, 0x00, 0xd3, 0x60, 0xdb, 0x40, 0xdb, 0x20, 0x10, 0xef, 0xc1, 0xf1, 0xc9, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x13
|
||||
};
|
Loading…
x
Reference in New Issue
Block a user