Setup cmake project
This commit is contained in:
8
CMakeLists.txt
Normal file
8
CMakeLists.txt
Normal file
@ -0,0 +1,8 @@
|
||||
cmake_minimum_required(VERSION 3.14)
|
||||
|
||||
project(ChUrlOS)
|
||||
|
||||
add_subdirectory(cmake)
|
||||
|
||||
set(CMAKE_VERBOSE_MAKEFILE ON)
|
||||
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
36
cmake/CMakeLists.txt
Normal file
36
cmake/CMakeLists.txt
Normal file
@ -0,0 +1,36 @@
|
||||
cmake_minimum_required(VERSION 3.14)
|
||||
|
||||
# Set source directory variables
|
||||
set(CHURLOS_ROOT_DIR "${CMAKE_CURRENT_LIST_DIR}/..")
|
||||
set(CHURLOS_SRC_DIR "${CHURLOS_ROOT_DIR}/src")
|
||||
set(CHURLOS_TOOL_DIR "${CHURLOS_ROOT_DIR}/tools")
|
||||
|
||||
# Set output directory variables
|
||||
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/static)
|
||||
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/shared)
|
||||
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
|
||||
|
||||
# Force out of source build
|
||||
message(STATUS "Force out of source build check...")
|
||||
string(COMPARE EQUAL "${CMAKE_SOURCE_DIR}" "${CMAKE_BINARY_DIR}" insource)
|
||||
if (insource)
|
||||
message(FATAL_ERROR "Please do not build in your source dir. Use a dedicated build folder!")
|
||||
endif ()
|
||||
|
||||
# Set compiler-flags
|
||||
ENABLE_LANGUAGE(ASM_NASM)
|
||||
set(CMAKE_ASM_NASM_OBJECT_FORMAT "elf32")
|
||||
set(CMAKE_ASM_NASM_INCLUDES "${CHURLOS_SRC_DIR}/")
|
||||
set(CMAKE_ASM_NASM_COMPILE_OBJECT "<CMAKE_ASM_NASM_COMPILER> -I${CMAKE_ASM_NASM_INCLUDES} -f ${CMAKE_ASM_NASM_OBJECT_FORMAT} -o <OBJECT> <SOURCE>")
|
||||
set(CMAKE_C_FLAGS "-m32 -march=i386 -mfpmath=387 -mno-mmx -mno-sse -mno-avx -Wall -fno-stack-protector -nostdlib -fno-pic -no-pie -ffreestanding")
|
||||
if(CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 9)
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mmanual-endbr")
|
||||
endif()
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_C_FLAGS} -Wl,--build-id=none -Wno-non-virtual-dtor -fno-threadsafe-statics -Wplacement-new=0 -fno-use-cxa-atexit -fno-rtti -fno-exceptions -std=c++20 -T ${CHURLOS_SRC_DIR}/link.ld")
|
||||
|
||||
# Add subdirectories
|
||||
add_subdirectory(bootdisk)
|
||||
add_subdirectory(device)
|
||||
add_subdirectory(kernel)
|
||||
add_subdirectory(lib)
|
||||
add_subdirectory(system)
|
30
cmake/bootdisk/CMakeLists.txt
Normal file
30
cmake/bootdisk/CMakeLists.txt
Normal file
@ -0,0 +1,30 @@
|
||||
cmake_minimum_required(VERSION 3.14)
|
||||
|
||||
project(bootdisk)
|
||||
message(STATUS "Project " ${PROJECT_NAME})
|
||||
|
||||
# BIOS-dev.code:total-tracks:-heads:-sectors:start-track:-head:-sector
|
||||
# Default-Werte fuer Boot von Floppy (USB/HD erkennt bootsect.asm selbst):
|
||||
set(BOOTDEVICE "0:80:2:18:0:0:1")
|
||||
|
||||
add_custom_command(OUTPUT "${CHURLOS_ROOT_DIR}/bootdisk.vmi"
|
||||
BYPRODUCTS "${CMAKE_BINARY_DIR}/bootsect" "${CMAKE_BINARY_DIR}/setup" "${CMAKE_BINARY_DIR}/build" "${CMAKE_BINARY_DIR}/system.img" "${CMAKE_BINARY_DIR}/bootdisk.img" "${CMAKE_BINARY_DIR}/bootdisk.vmi"
|
||||
|
||||
# Compile bootsect and setup code
|
||||
COMMAND nasm -f bin -o "${CMAKE_BINARY_DIR}/bootsect" "${CHURLOS_SRC_DIR}/bootdisk/bootsect.asm"
|
||||
COMMAND nasm -f bin -o "${CMAKE_BINARY_DIR}/setup" "${CHURLOS_SRC_DIR}/bootdisk/setup.asm"
|
||||
|
||||
# Compile build code
|
||||
COMMAND gcc -o "${CMAKE_BINARY_DIR}/build" "${CHURLOS_SRC_DIR}/bootdisk/build.c"
|
||||
|
||||
# Build system.img
|
||||
COMMAND objcopy -O binary "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/system" "${CMAKE_BINARY_DIR}/system.img"
|
||||
|
||||
# Build bootdisk
|
||||
COMMAND "${CMAKE_BINARY_DIR}/build" "${CMAKE_BINARY_DIR}/bootsect" "${CMAKE_BINARY_DIR}/setup" "${CMAKE_BINARY_DIR}/system.img" ${BOOTDEVICE} "${CMAKE_BINARY_DIR}/bootdisk.img"
|
||||
COMMAND dd if="${CMAKE_BINARY_DIR}/bootdisk.img" of="${CMAKE_BINARY_DIR}/bootdisk.vmi" bs=1474560 conv=sync
|
||||
COMMAND /run/current-system/sw/bin/cp "${CMAKE_BINARY_DIR}/bootdisk.vmi" "${CHURLOS_ROOT_DIR}/bootdisk.vmi"
|
||||
DEPENDS system
|
||||
)
|
||||
|
||||
add_custom_target(${PROJECT_NAME} DEPENDS ${CHURLOS_ROOT_DIR}/bootdisk.vmi)
|
18
cmake/device/CMakeLists.txt
Normal file
18
cmake/device/CMakeLists.txt
Normal file
@ -0,0 +1,18 @@
|
||||
cmake_minimum_required(VERSION 3.14)
|
||||
|
||||
project(device)
|
||||
message(STATUS "Project " ${PROJECT_NAME})
|
||||
|
||||
include_directories(${CHURLOS_SRC_DIR})
|
||||
|
||||
add_library(${PROJECT_NAME} STATIC ${SOURCE_FILES})
|
||||
|
||||
# Add subdirectories
|
||||
add_subdirectory(bios)
|
||||
add_subdirectory(cpu)
|
||||
add_subdirectory(graphics)
|
||||
add_subdirectory(hid)
|
||||
add_subdirectory(interrupt)
|
||||
add_subdirectory(port)
|
||||
add_subdirectory(sound)
|
||||
add_subdirectory(time)
|
5
cmake/device/bios/CMakeLists.txt
Normal file
5
cmake/device/bios/CMakeLists.txt
Normal file
@ -0,0 +1,5 @@
|
||||
cmake_minimum_required(VERSION 3.14)
|
||||
|
||||
target_sources(device PUBLIC
|
||||
${CHURLOS_SRC_DIR}/device/bios/BIOS.cc
|
||||
)
|
5
cmake/device/cpu/CMakeLists.txt
Normal file
5
cmake/device/cpu/CMakeLists.txt
Normal file
@ -0,0 +1,5 @@
|
||||
cmake_minimum_required(VERSION 3.14)
|
||||
|
||||
# target_sources(device PUBLIC
|
||||
# ${CHURLOS_SRC_DIR}/
|
||||
# )
|
9
cmake/device/graphics/CMakeLists.txt
Normal file
9
cmake/device/graphics/CMakeLists.txt
Normal file
@ -0,0 +1,9 @@
|
||||
cmake_minimum_required(VERSION 3.14)
|
||||
|
||||
target_sources(device PUBLIC
|
||||
${CHURLOS_SRC_DIR}/device/graphics/CGA.cc
|
||||
${CHURLOS_SRC_DIR}/device/graphics/CGA_Stream.cc
|
||||
${CHURLOS_SRC_DIR}/device/graphics/Fonts.cc
|
||||
${CHURLOS_SRC_DIR}/device/graphics/LFBgraphics.cc
|
||||
${CHURLOS_SRC_DIR}/device/graphics/VESA.cc
|
||||
)
|
5
cmake/device/hid/CMakeLists.txt
Normal file
5
cmake/device/hid/CMakeLists.txt
Normal file
@ -0,0 +1,5 @@
|
||||
cmake_minimum_required(VERSION 3.14)
|
||||
|
||||
target_sources(device PUBLIC
|
||||
${CHURLOS_SRC_DIR}/device/hid/Keyboard.cc
|
||||
)
|
5
cmake/device/interrupt/CMakeLists.txt
Normal file
5
cmake/device/interrupt/CMakeLists.txt
Normal file
@ -0,0 +1,5 @@
|
||||
cmake_minimum_required(VERSION 3.14)
|
||||
|
||||
target_sources(device PUBLIC
|
||||
${CHURLOS_SRC_DIR}/device/interrupt/PIC.cc
|
||||
)
|
5
cmake/device/port/CMakeLists.txt
Normal file
5
cmake/device/port/CMakeLists.txt
Normal file
@ -0,0 +1,5 @@
|
||||
cmake_minimum_required(VERSION 3.14)
|
||||
|
||||
target_sources(device PUBLIC
|
||||
${CHURLOS_SRC_DIR}/device/port/SerialOut.cc
|
||||
)
|
5
cmake/device/sound/CMakeLists.txt
Normal file
5
cmake/device/sound/CMakeLists.txt
Normal file
@ -0,0 +1,5 @@
|
||||
cmake_minimum_required(VERSION 3.14)
|
||||
|
||||
target_sources(device PUBLIC
|
||||
${CHURLOS_SRC_DIR}/device/sound/PCSPK.cc
|
||||
)
|
5
cmake/device/time/CMakeLists.txt
Normal file
5
cmake/device/time/CMakeLists.txt
Normal file
@ -0,0 +1,5 @@
|
||||
cmake_minimum_required(VERSION 3.14)
|
||||
|
||||
target_sources(device PUBLIC
|
||||
${CHURLOS_SRC_DIR}/device/time/PIT.cc
|
||||
)
|
17
cmake/kernel/CMakeLists.txt
Normal file
17
cmake/kernel/CMakeLists.txt
Normal file
@ -0,0 +1,17 @@
|
||||
cmake_minimum_required(VERSION 3.14)
|
||||
|
||||
project(kernel)
|
||||
message(STATUS "Project " ${PROJECT_NAME})
|
||||
|
||||
include_directories(${CHURLOS_SRC_DIR})
|
||||
|
||||
add_library(${PROJECT_NAME} STATIC ${SOURCE_FILES})
|
||||
|
||||
# Add subdirectories
|
||||
add_subdirectory(demo)
|
||||
add_subdirectory(event)
|
||||
add_subdirectory(interrupt)
|
||||
add_subdirectory(log)
|
||||
add_subdirectory(memory)
|
||||
add_subdirectory(process)
|
||||
add_subdirectory(system)
|
17
cmake/kernel/demo/CMakeLists.txt
Normal file
17
cmake/kernel/demo/CMakeLists.txt
Normal file
@ -0,0 +1,17 @@
|
||||
cmake_minimum_required(VERSION 3.14)
|
||||
|
||||
target_sources(kernel PUBLIC
|
||||
${CHURLOS_SRC_DIR}/kernel/demo/ArrayDemo.cc
|
||||
${CHURLOS_SRC_DIR}/kernel/demo/bmp_hhu.cc
|
||||
${CHURLOS_SRC_DIR}/kernel/demo/HeapDemo.cc
|
||||
${CHURLOS_SRC_DIR}/kernel/demo/KeyboardDemo.cc
|
||||
${CHURLOS_SRC_DIR}/kernel/demo/MainMenu.cc
|
||||
${CHURLOS_SRC_DIR}/kernel/demo/PagingDemo.cc
|
||||
${CHURLOS_SRC_DIR}/kernel/demo/PCSPKdemo.cc
|
||||
${CHURLOS_SRC_DIR}/kernel/demo/PreemptiveThreadDemo.cc
|
||||
${CHURLOS_SRC_DIR}/kernel/demo/SmartPointerDemo.cc
|
||||
${CHURLOS_SRC_DIR}/kernel/demo/StringDemo.cc
|
||||
${CHURLOS_SRC_DIR}/kernel/demo/TextDemo.cc
|
||||
${CHURLOS_SRC_DIR}/kernel/demo/VBEdemo.cc
|
||||
${CHURLOS_SRC_DIR}/kernel/demo/VectorDemo.cc
|
||||
)
|
6
cmake/kernel/event/CMakeLists.txt
Normal file
6
cmake/kernel/event/CMakeLists.txt
Normal file
@ -0,0 +1,6 @@
|
||||
cmake_minimum_required(VERSION 3.14)
|
||||
|
||||
target_sources(kernel PUBLIC
|
||||
${CHURLOS_SRC_DIR}/kernel/event/KeyEventListener.cc
|
||||
${CHURLOS_SRC_DIR}/kernel/event/KeyEventManager.cc
|
||||
)
|
6
cmake/kernel/interrupt/CMakeLists.txt
Normal file
6
cmake/kernel/interrupt/CMakeLists.txt
Normal file
@ -0,0 +1,6 @@
|
||||
cmake_minimum_required(VERSION 3.14)
|
||||
|
||||
target_sources(kernel PUBLIC
|
||||
${CHURLOS_SRC_DIR}/kernel/interrupt/Bluescreen.cc
|
||||
${CHURLOS_SRC_DIR}/kernel/interrupt/IntDispatcher.cc
|
||||
)
|
5
cmake/kernel/log/CMakeLists.txt
Normal file
5
cmake/kernel/log/CMakeLists.txt
Normal file
@ -0,0 +1,5 @@
|
||||
cmake_minimum_required(VERSION 3.14)
|
||||
|
||||
target_sources(kernel PUBLIC
|
||||
${CHURLOS_SRC_DIR}/kernel/log/Logger.cc
|
||||
)
|
8
cmake/kernel/memory/CMakeLists.txt
Normal file
8
cmake/kernel/memory/CMakeLists.txt
Normal file
@ -0,0 +1,8 @@
|
||||
cmake_minimum_required(VERSION 3.14)
|
||||
|
||||
target_sources(kernel PUBLIC
|
||||
${CHURLOS_SRC_DIR}/kernel/memory/Allocator.cc
|
||||
${CHURLOS_SRC_DIR}/kernel/memory/BumpAllocator.cc
|
||||
${CHURLOS_SRC_DIR}/kernel/memory/LinkedListAllocator.cc
|
||||
${CHURLOS_SRC_DIR}/kernel/memory/Paging.cc
|
||||
)
|
7
cmake/kernel/process/CMakeLists.txt
Normal file
7
cmake/kernel/process/CMakeLists.txt
Normal file
@ -0,0 +1,7 @@
|
||||
cmake_minimum_required(VERSION 3.14)
|
||||
|
||||
target_sources(kernel PUBLIC
|
||||
${CHURLOS_SRC_DIR}/kernel/process/Scheduler.cc
|
||||
${CHURLOS_SRC_DIR}/kernel/process/Thread.cc
|
||||
${CHURLOS_SRC_DIR}/kernel/process/Thread.asm
|
||||
)
|
5
cmake/kernel/system/CMakeLists.txt
Normal file
5
cmake/kernel/system/CMakeLists.txt
Normal file
@ -0,0 +1,5 @@
|
||||
cmake_minimum_required(VERSION 3.14)
|
||||
|
||||
target_sources(kernel PUBLIC
|
||||
${CHURLOS_SRC_DIR}/kernel/system/Globals.cc
|
||||
)
|
14
cmake/lib/CMakeLists.txt
Normal file
14
cmake/lib/CMakeLists.txt
Normal file
@ -0,0 +1,14 @@
|
||||
cmake_minimum_required(VERSION 3.14)
|
||||
|
||||
project(lib)
|
||||
message(STATUS "Project " ${PROJECT_NAME})
|
||||
|
||||
include_directories(${CHURLOS_SRC_DIR})
|
||||
|
||||
add_library(${PROJECT_NAME} STATIC ${SOURCE_FILES})
|
||||
|
||||
# Add subdirectories
|
||||
add_subdirectory(async)
|
||||
add_subdirectory(mem)
|
||||
add_subdirectory(stream)
|
||||
add_subdirectory(util)
|
6
cmake/lib/async/CMakeLists.txt
Normal file
6
cmake/lib/async/CMakeLists.txt
Normal file
@ -0,0 +1,6 @@
|
||||
cmake_minimum_required(VERSION 3.14)
|
||||
|
||||
target_sources(lib PUBLIC
|
||||
${CHURLOS_SRC_DIR}/lib/async/Semaphore.cc
|
||||
${CHURLOS_SRC_DIR}/lib/async/SpinLock.cc
|
||||
)
|
5
cmake/lib/mem/CMakeLists.txt
Normal file
5
cmake/lib/mem/CMakeLists.txt
Normal file
@ -0,0 +1,5 @@
|
||||
cmake_minimum_required(VERSION 3.14)
|
||||
|
||||
target_sources(lib PUBLIC
|
||||
${CHURLOS_SRC_DIR}/lib/mem/Memory.cc
|
||||
)
|
5
cmake/lib/stream/CMakeLists.txt
Normal file
5
cmake/lib/stream/CMakeLists.txt
Normal file
@ -0,0 +1,5 @@
|
||||
cmake_minimum_required(VERSION 3.14)
|
||||
|
||||
target_sources(lib PUBLIC
|
||||
${CHURLOS_SRC_DIR}/lib/stream/OutStream.cc
|
||||
)
|
7
cmake/lib/util/CMakeLists.txt
Normal file
7
cmake/lib/util/CMakeLists.txt
Normal file
@ -0,0 +1,7 @@
|
||||
cmake_minimum_required(VERSION 3.14)
|
||||
|
||||
target_sources(lib PUBLIC
|
||||
${CHURLOS_SRC_DIR}/lib/util/String.cc
|
||||
${CHURLOS_SRC_DIR}/lib/util/StringBuffer.cc
|
||||
${CHURLOS_SRC_DIR}/lib/util/StringView.cc
|
||||
)
|
16
cmake/system/CMakeLists.txt
Normal file
16
cmake/system/CMakeLists.txt
Normal file
@ -0,0 +1,16 @@
|
||||
cmake_minimum_required(VERSION 3.14)
|
||||
|
||||
project(system)
|
||||
message(STATUS "Project " ${PROJECT_NAME})
|
||||
|
||||
include_directories(${CHURLOS_SRC_DIR})
|
||||
|
||||
# Set source files
|
||||
set(SOURCE_FILES
|
||||
${CHURLOS_SRC_DIR}/startup.asm
|
||||
${CHURLOS_SRC_DIR}/main.cc
|
||||
)
|
||||
|
||||
add_executable(${PROJECT_NAME} ${SOURCE_FILES})
|
||||
|
||||
target_link_libraries(${PROJECT_NAME} device kernel lib)
|
324
src/bootdisk/bootsect.asm
Normal file
324
src/bootdisk/bootsect.asm
Normal file
@ -0,0 +1,324 @@
|
||||
; $Id: bootsect.asm 5001 2012-10-12 11:34:05Z os $
|
||||
|
||||
;******************************************************************************
|
||||
;* Betriebssysteme *
|
||||
;*----------------------------------------------------------------------------*
|
||||
;* *
|
||||
;* B O O T S E C T *
|
||||
;* *
|
||||
;*----------------------------------------------------------------------------*
|
||||
;* Code fuer den Disketten-Bootblock des System-Images. Das BIOS laedt den *
|
||||
;* ersten Block einer Diskette (den Bootblock) beim Starten des Rechner in *
|
||||
;* den Hauptspeicher und fuehrt ihn aus. Der Programmcode des Bootblocks *
|
||||
;* laedt nun das restliche System und fuehrt es aus. *
|
||||
;******************************************************************************
|
||||
|
||||
;
|
||||
; Konstanten
|
||||
;
|
||||
BIOSSEG equ 0x07c0 ; Hierher wird der Bootsector
|
||||
; vom BIOS geladen
|
||||
BOOTSEG equ 0x0060 ; Hierher verschiebt sich der
|
||||
; Boot-Code
|
||||
SETUPSEG equ 0x9000 ; Hierher laedt der Boot-Code den
|
||||
; Setup-Code (max. 64K inkl. Stack)
|
||||
SYSTEMSEG equ 0x1000 ; System-Code (max. 512K)
|
||||
SECTORSZ equ 512 ; Groesse eines Sektors in Bytes
|
||||
|
||||
[SECTION .text]
|
||||
|
||||
;
|
||||
; Boot-Code
|
||||
;
|
||||
bootsector:
|
||||
jmp skip_data
|
||||
|
||||
;------------------------------------------------------------------------------
|
||||
;
|
||||
; Datenbereich, der von 'build' beim Erzeugen der Boot-Diskette
|
||||
; gefuellt wird.
|
||||
;
|
||||
pad:
|
||||
times 4+bootsector-$ db 0 ; Bytes zum Auffuellen, damit 'total_tracks' an einer
|
||||
; geraden und tools/build.c bekannten Adresse liegt
|
||||
total_tracks:
|
||||
dw 0 ; Anzahl der Tracks der Diskette
|
||||
total_heads:
|
||||
dw 0 ; Anzahl der Seiten der Diskette
|
||||
total_sectors:
|
||||
dw 0 ; Anzahl der Sektoren pro Track
|
||||
setup_sectors:
|
||||
dw 0 ; Anzahl der Sektoren, die der Setup-Code einnimmt
|
||||
system_sectors:
|
||||
dw 0 ; Anzahl der Sektoren, die das System einnimmt
|
||||
bootdevice:
|
||||
db 0 ; BIOS Geraetecode: 00: Disk A, 01: Disk B, ..., 0x80 HD0, ...
|
||||
curr_track:
|
||||
db 0 ; Track, bei dem die Diskette/Partition beginnt
|
||||
curr_head:
|
||||
db 0 ; Head, bei dem die Diskette/Partition beginnt
|
||||
curr_sector:
|
||||
db 0 ; Sector, bei dem die Diskette/Partition beginnt
|
||||
|
||||
;-----------------------------------------------------------------------
|
||||
|
||||
;
|
||||
; Kopieren des Bootsectors
|
||||
;
|
||||
skip_data:
|
||||
mov bl,dl ; vom BIOS uebergebenes Boot-Device sichern
|
||||
|
||||
mov ax,BIOSSEG
|
||||
mov ds,ax
|
||||
xor si,si
|
||||
mov ax,BOOTSEG
|
||||
mov es,ax
|
||||
xor di,di
|
||||
mov cx,SECTORSZ/2
|
||||
rep movsw
|
||||
;
|
||||
; Ausfuehrung durch die Kopie fortsetzen
|
||||
;
|
||||
jmp BOOTSEG:start
|
||||
;
|
||||
; Segmentregister initialisieren und Platz fuer den Stack schaffen
|
||||
;
|
||||
start:
|
||||
mov ax,cs ; Daten-, Stack- und Codesegment sollen
|
||||
mov ds,ax ; hierher zeigen.
|
||||
mov ss,ax
|
||||
mov sp,4*SECTORSZ ; Drei Sektoren als Stack freilassen
|
||||
|
||||
mov [bootdevice],bl ; zuvor gesichertes Boot-Device permanent ablegen
|
||||
|
||||
;
|
||||
; Ausgabe einer Meldung mit Hilfe eines BIOS-Aufrufs
|
||||
;
|
||||
mov ah,0x03 ; Feststellen der Cursor-Position
|
||||
xor bh,bh
|
||||
int 0x10
|
||||
|
||||
mov cx,13
|
||||
mov bx,0x0007 ; page 0, attribute 7 (normal)
|
||||
mov ax,ds
|
||||
mov es,ax
|
||||
mov bp,bootmessage
|
||||
mov ax,0x1301 ; Ausgabe des Textes, Cursor bewegen
|
||||
int 0x10
|
||||
;
|
||||
; Nachladen des Setup-Codes und des Systems selbst.
|
||||
;
|
||||
xor ah,ah ; Reset des Disketten-/Plattencontrollers
|
||||
mov dl,[bootdevice]
|
||||
int 0x13
|
||||
;
|
||||
; Informationen ueber die Laufwerksgeometrie holen
|
||||
;
|
||||
hdd_probe:
|
||||
mov dl,[bootdevice]
|
||||
test dl,0x80
|
||||
jz load_setup ; Floppy mit den Standardparametern laden
|
||||
mov ah,0x8
|
||||
int 0x13
|
||||
jc load_setup ; CF bei Fehler gesetzt
|
||||
mov [total_heads],dh
|
||||
mov ax,cx ; CX sichern
|
||||
and ax,0x3f
|
||||
mov [total_sectors],ax
|
||||
mov ax,cx
|
||||
shr ax,6
|
||||
mov [total_tracks],ax
|
||||
|
||||
;
|
||||
; Weiterstellen der Disketten-/Plattenposition um 1 (Bootblock)
|
||||
;
|
||||
load_setup:
|
||||
call step_disk
|
||||
|
||||
;
|
||||
; Laden des Setup-Codes
|
||||
;
|
||||
mov word [curr_segment],SETUPSEG
|
||||
mov word [curr_offset],0
|
||||
mov ax,[setup_sectors]
|
||||
call load
|
||||
;
|
||||
; Laden des Kernels
|
||||
;
|
||||
mov word [curr_segment],SYSTEMSEG
|
||||
mov word [curr_offset],0
|
||||
mov ax,[system_sectors]
|
||||
call load
|
||||
;
|
||||
; Floppy wieder abschalten
|
||||
;
|
||||
call stop_floppy_motor
|
||||
;
|
||||
; Start des Setup-Codes
|
||||
;
|
||||
mov ax, [system_sectors] ; Speichere Anzahl an System-Sektoren in AX.
|
||||
jmp SETUPSEG:0
|
||||
|
||||
;
|
||||
; load
|
||||
;
|
||||
; Die 'ax' Sektoren von der Diskette in den Hauptspeicher. Die Position auf
|
||||
; der Diskette muss vorher in curr_head/curr_track/curr_sector und die
|
||||
; Position im Hauptspeicher in curr_segment/curr_offset stehen. Die Positionen
|
||||
; werden entsprechend der geladenen Sektoren weitergestellt.
|
||||
;
|
||||
load:
|
||||
mov [to_load],ax
|
||||
l_next_part:
|
||||
mov al,[curr_head]
|
||||
mov [last_head],al
|
||||
mov al,[curr_track]
|
||||
mov [last_track],al
|
||||
mov al,[curr_sector]
|
||||
mov [last_sector],al
|
||||
mov ax,[curr_segment]
|
||||
mov [last_segment],ax
|
||||
mov ax,[curr_offset]
|
||||
mov [last_offset],ax
|
||||
|
||||
mov al,0
|
||||
|
||||
l_loop: call step
|
||||
|
||||
cmp byte [curr_sector],0x01
|
||||
je l_now
|
||||
cmp word [curr_offset],0x0000
|
||||
je l_now
|
||||
cmp al,[to_load]
|
||||
jne l_loop
|
||||
|
||||
l_now:
|
||||
push ax
|
||||
mov dl,[bootdevice]
|
||||
mov dh,[last_head]
|
||||
mov ch,[last_track]
|
||||
mov cl,[last_sector]
|
||||
mov bx,[last_segment]
|
||||
mov es,bx
|
||||
mov bx,[last_offset]
|
||||
mov ah,0x02 ; Funktionscode fuer 'Lesen'
|
||||
int 0x13
|
||||
pop ax
|
||||
|
||||
push ax
|
||||
call print_dot
|
||||
pop ax
|
||||
|
||||
mov ah,0
|
||||
sub [to_load],ax
|
||||
jne l_next_part
|
||||
ret
|
||||
|
||||
;
|
||||
; step
|
||||
;
|
||||
; Stellt die aktuelle Position im Hauptspeicher und auf der Diskette
|
||||
; um einen Sektor (512 Byte) weiter.
|
||||
;
|
||||
step: add al,1
|
||||
call step_disk
|
||||
call step_memory
|
||||
ret
|
||||
|
||||
step_disk:
|
||||
mov bl,[curr_sector]
|
||||
add bl,1
|
||||
mov [curr_sector],bl
|
||||
cmp bl,[total_sectors]
|
||||
jle l_1
|
||||
mov byte [curr_sector],1
|
||||
|
||||
mov bl,[curr_head]
|
||||
add bl,1
|
||||
mov [curr_head],bl
|
||||
cmp bl,[total_heads]
|
||||
jne l_1
|
||||
mov byte [curr_head],0
|
||||
|
||||
mov bl,[curr_track]
|
||||
add bl,1
|
||||
mov [curr_track],bl
|
||||
|
||||
l_1: ret
|
||||
|
||||
step_memory:
|
||||
mov bx,[curr_offset]
|
||||
add bx,SECTORSZ
|
||||
mov [curr_offset],bx
|
||||
test bx,0xffff
|
||||
jne l_2
|
||||
mov bx,[curr_segment]
|
||||
add bx,0x1000 ; 64 KByte weiterstellen
|
||||
mov [curr_segment],bx
|
||||
|
||||
l_2 ret
|
||||
|
||||
;
|
||||
; Ausgabe eines Stern ('*') mit Hilfe eines BIOS-Aufrufs
|
||||
;
|
||||
print_dot:
|
||||
mov ah,0x03 ; Feststellen der Cursor-Position
|
||||
xor bh,bh
|
||||
int 0x10
|
||||
|
||||
mov cx,1
|
||||
mov bx,0x0007 ; page 0, attribute 7 (normal)
|
||||
mov ax,ds
|
||||
mov es,ax
|
||||
mov bp,dot
|
||||
mov ax,0x1301 ; Ausgabe des Textes, Cursor bewegen
|
||||
int 0x10
|
||||
|
||||
ret
|
||||
|
||||
;
|
||||
; stop_floppy_motor
|
||||
;
|
||||
; Stopt den Motor der Floppy, da das BIOS dazu in Kuerze nicht mehr in
|
||||
; der Lage sein wird. Egal, ob von Floppy oder Platte gebootet wurde.
|
||||
;
|
||||
stop_floppy_motor:
|
||||
mov dx,0x3f2
|
||||
xor al,al
|
||||
out dx,al
|
||||
ret
|
||||
|
||||
;
|
||||
; Datenbereich
|
||||
;
|
||||
|
||||
bootmessage:
|
||||
db 13,10
|
||||
db 'booting ... '
|
||||
|
||||
dot:
|
||||
db '*'
|
||||
|
||||
to_load:
|
||||
dw 0
|
||||
curr_segment:
|
||||
dw 0
|
||||
curr_offset:
|
||||
dw 0
|
||||
|
||||
last_head:
|
||||
db 0
|
||||
last_track:
|
||||
db 0
|
||||
last_sector:
|
||||
db 0
|
||||
last_segment:
|
||||
dw 0
|
||||
last_offset:
|
||||
dw 0
|
||||
|
||||
unused:
|
||||
times bootsector+510-$ db 0
|
||||
|
||||
mark:
|
||||
dw 0xaa55
|
149
src/bootdisk/build.c
Executable file
149
src/bootdisk/build.c
Executable file
@ -0,0 +1,149 @@
|
||||
#include <stdio.h> /* fprintf */
|
||||
#include <string.h>
|
||||
#include <stdlib.h> /* contains exit */
|
||||
#include <unistd.h> /* contains read/write */
|
||||
#include <fcntl.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#if !defined(DOS) && !defined(Win32)
|
||||
#define O_BINARY 0
|
||||
#endif
|
||||
|
||||
#define SECTOR 512
|
||||
|
||||
void die(const char *str) {
|
||||
fprintf(stderr, "%s\n", str);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
int fd, fd_out;
|
||||
char bootsector[SECTOR];
|
||||
char setupsector[SECTOR];
|
||||
struct stat info;
|
||||
unsigned short setup_size;
|
||||
int bytes_read, to_read;
|
||||
unsigned int dc, st, sh, ss, tt, th, ts;
|
||||
unsigned char bios_device_code, start_track, start_head, start_sector;
|
||||
unsigned short total_tracks, total_heads, total_sectors;
|
||||
unsigned short system_sectors;
|
||||
|
||||
if (argc != 6)
|
||||
die("usage: build bootsector setup-code system-image dev.info bootdisk-image\n\n"
|
||||
"dev.info: BIOS-dev.code:total-tracks:-heads:-sectors:start-track:-head:-sector\n"
|
||||
"BIOS-devicecode: 0=fd0, 1=fd1, ..., 128=hd0, 129=hd1, ...\n"
|
||||
"Example: to boot from a 3.5\" floppy disk use \"0:80:2:18:0:0:1\"\n");
|
||||
|
||||
sscanf(argv[4], "%u:%u:%u:%u:%u:%u:%u", &dc, &tt, &th, &ts, &st, &sh, &ss);
|
||||
bios_device_code = (unsigned char) dc;
|
||||
total_tracks = (unsigned short) tt;
|
||||
total_sectors = (unsigned short) ts;
|
||||
total_heads = (unsigned short) th;
|
||||
start_track = (unsigned char) st;
|
||||
start_head = (unsigned char) sh;
|
||||
start_sector = (unsigned char) ss;
|
||||
|
||||
printf("BIOS-devicecode: 0x%x\n", bios_device_code);
|
||||
printf("Total T/H/S: (%d/%d/%d)\n", total_tracks, total_heads,
|
||||
total_sectors);
|
||||
printf("Start T/H/S: (%d/%d/%d)\n\n", start_track, start_head,
|
||||
start_sector);
|
||||
|
||||
if ((fd_out = open(argv[5], O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0644)) < 0)
|
||||
die("Unable to open output file.");
|
||||
|
||||
if ((fd = open(argv[1], O_RDONLY | O_BINARY, 0)) < 0)
|
||||
die("Unable to open input file.");
|
||||
|
||||
if (read(fd, bootsector, SECTOR) < 0)
|
||||
die("Unable to read bootsector.");
|
||||
|
||||
close(fd);
|
||||
|
||||
if (stat(argv[2], &info) != 0)
|
||||
die("Can't stat setup file.");
|
||||
|
||||
setup_size = (unsigned short)
|
||||
((info.st_size + SECTOR - 1) / SECTOR);
|
||||
printf("Setup size is %d sectors.\n", (int) setup_size);
|
||||
|
||||
if (stat(argv[3], &info) != 0)
|
||||
die("Can't stat system file.");
|
||||
to_read = info.st_size;
|
||||
printf("System size is %d bytes.\n", to_read);
|
||||
|
||||
system_sectors = (to_read + SECTOR - 1) / SECTOR;
|
||||
printf("# System sectors is %d.\n", system_sectors);
|
||||
|
||||
#if 0
|
||||
*(unsigned short*)(bootsector+4) = total_tracks;
|
||||
*(unsigned short*)(bootsector+6) = total_heads;
|
||||
*(unsigned short*)(bootsector+8) = total_sectors;
|
||||
|
||||
*(unsigned short*)(bootsector+10) = setup_size;
|
||||
*(unsigned short*)(bootsector+12) =
|
||||
(unsigned short)((to_read + SECTOR - 1) / SECTOR);
|
||||
*(unsigned char*)(bootsector+14) = bios_device_code;
|
||||
*(unsigned char*)(bootsector+15) = start_track;
|
||||
*(unsigned char*)(bootsector+16) = start_head;
|
||||
*(unsigned char*)(bootsector+17) = start_sector;
|
||||
#else
|
||||
*(unsigned char *) (bootsector + 4) = (total_tracks) & 0xff;
|
||||
*(unsigned char *) (bootsector + 5) = (total_tracks >> 8) & 0xff;
|
||||
*(unsigned char *) (bootsector + 6) = (total_heads) & 0xff;
|
||||
*(unsigned char *) (bootsector + 7) = (total_heads >> 8) & 0xff;
|
||||
*(unsigned char *) (bootsector + 8) = (total_sectors) & 0xff;
|
||||
*(unsigned char *) (bootsector + 9) = (total_sectors >> 8) & 0xff;
|
||||
|
||||
*(unsigned char *) (bootsector + 10) = (setup_size) & 0xff;
|
||||
*(unsigned char *) (bootsector + 11) = (setup_size >> 8) & 0xff;
|
||||
*(unsigned char *) (bootsector + 12) = system_sectors & 0xff;
|
||||
*(unsigned char *) (bootsector + 13) = (system_sectors >> 8) & 0xff;
|
||||
*(unsigned char *) (bootsector + 14) = bios_device_code;
|
||||
*(unsigned char *) (bootsector + 15) = start_track;
|
||||
*(unsigned char *) (bootsector + 16) = start_head;
|
||||
*(unsigned char *) (bootsector + 17) = start_sector;
|
||||
#endif
|
||||
|
||||
write(fd_out, bootsector, SECTOR);
|
||||
|
||||
if ((fd = open(argv[2], O_RDONLY | O_BINARY, 0)) < 0)
|
||||
die("Unable to open setup file.");
|
||||
|
||||
do {
|
||||
if ((bytes_read = read(fd, setupsector, SECTOR)) < 0)
|
||||
die("Unable to read setup.");
|
||||
|
||||
if (bytes_read > 0)
|
||||
write(fd_out, setupsector, SECTOR);
|
||||
|
||||
} while (bytes_read > 0);
|
||||
|
||||
|
||||
close(fd);
|
||||
|
||||
if ((fd = open(argv[3], O_RDONLY | O_BINARY, 0)) < 0)
|
||||
die("Unable to open system file.");
|
||||
|
||||
while (to_read > 0) {
|
||||
int l;
|
||||
|
||||
l = (to_read < SECTOR) ? to_read : SECTOR;
|
||||
|
||||
if ((bytes_read = read(fd, setupsector, l)) != l)
|
||||
die("Unable to read system.");
|
||||
|
||||
write(fd_out, setupsector, l);
|
||||
|
||||
to_read -= l;
|
||||
}
|
||||
|
||||
close(fd);
|
||||
close(fd_out);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
200
src/bootdisk/setup.asm
Normal file
200
src/bootdisk/setup.asm
Normal file
@ -0,0 +1,200 @@
|
||||
; $Id: setup.asm 1484 2009-02-11 21:03:19Z hsc $
|
||||
|
||||
;******************************************************************************
|
||||
;* Betriebssysteme *
|
||||
;*----------------------------------------------------------------------------*
|
||||
;* *
|
||||
;* S E T U P *
|
||||
;* *
|
||||
;*----------------------------------------------------------------------------*
|
||||
;* Der Setup-Code liegt im System-Image direkt hinter dem Bootsektor und wird *
|
||||
;* von diesem direkt nach dem Laden aktiviert. Der Code wird noch im *
|
||||
;* 'Real-Mode' gestartet, so dass zu Beginn auch noch BIOS-Aufrufe erlaubt *
|
||||
;* sind. Dann werden jedoch alle Interrupts verboten, die Adressleitung A20 *
|
||||
;* aktiviert und die Umschaltung in den 'Protected-Mode' vorgenommen. Alles *
|
||||
;* weitere uebernimmt der Startup-Code des Systems. *
|
||||
;******************************************************************************
|
||||
|
||||
;
|
||||
; Konstanten
|
||||
;
|
||||
SETUPSEG equ 0x9000 ; Setup-Code (max. 64K inkl. Stack)
|
||||
SYSTEMSEG equ 0x1000 ; System-Code (max. 512K)
|
||||
SECTORSZ equ 512 ; Groesse eines Sektors in Bytes
|
||||
SYSTEMSTART equ 0x100000 ; Hierhin wird das System nach Umschalten in den
|
||||
; Protected Mode kopiert, da GRUB das auch tut
|
||||
; (und GRUB kann nur an Adressen >1M laden).
|
||||
|
||||
[SECTION .text]
|
||||
[BITS 16]
|
||||
;
|
||||
; Segmentregister initialisieren
|
||||
;
|
||||
start:
|
||||
mov dx, ax ; Anzahl Systemsektoren in DX sichern.
|
||||
|
||||
mov ax,cs ; Daten-, Code- und Stacksegment sollen
|
||||
mov ds,ax ; hierher zeigen.
|
||||
mov ss,ax ; Alle drei Segment duerfen nicht mehr
|
||||
mov sp,0xfffe ; als 64 KByte einnehmen (zusammen).
|
||||
|
||||
mov [system_sectors], dx ; Anzahl der Systemsektoren im Speicher ablegen
|
||||
|
||||
;
|
||||
; Ausgabe einer Meldung mit Hilfe eines BIOS-Aufrufs
|
||||
;
|
||||
mov ah,0x03 ; Feststellen der Cursor-Position
|
||||
xor bh,bh
|
||||
int 0x10
|
||||
|
||||
mov cx,14
|
||||
mov bx,0x0007 ; page 0, attribute 7 (normal)
|
||||
mov ax,ds
|
||||
mov es,ax
|
||||
mov bp,setupmessage
|
||||
mov ax,0x1301 ; Ausgabe des Textes, Cursor bewegen
|
||||
int 0x10
|
||||
;
|
||||
; So, jetzt werden die Interrupts abgeschaltet
|
||||
;
|
||||
cli ; Maskierbare Interrupts verbieten
|
||||
mov al,0x80 ; NMI verbieten
|
||||
out 0x70,al
|
||||
;
|
||||
; IDT und GDT setzen
|
||||
;
|
||||
lidt [idt_48]
|
||||
lgdt [gdt_48]
|
||||
;
|
||||
; Aktivieren der Adressleitung A20
|
||||
;
|
||||
call empty_8042
|
||||
mov al,0xd1
|
||||
out 0x64,al
|
||||
call empty_8042
|
||||
mov al,0xdf
|
||||
out 0x60,al
|
||||
call empty_8042
|
||||
mov al,0xff
|
||||
out 0x64,al
|
||||
call empty_8042
|
||||
;
|
||||
; Moeglichen Koprozessor zuruecksetzen
|
||||
;
|
||||
xor ax,ax
|
||||
out 0xf0,al
|
||||
call delay
|
||||
out 0xf1,al
|
||||
call delay
|
||||
;
|
||||
; Umschalten in den Protected Mode
|
||||
;
|
||||
mov eax,cr0 ; Setze PM-Bit im Kontrollregister 1
|
||||
or eax,1
|
||||
mov cr0,eax
|
||||
|
||||
jmp dword 0x08:SETUPSEG*0x10+copy_system ; Far-Jump, um
|
||||
; a) fetch Pipeline zu leeren
|
||||
; b) CS Register sinnvoll zu belegen
|
||||
[BITS 32]
|
||||
; Arbeite jetzt im Protected Mode
|
||||
copy_system:
|
||||
;
|
||||
; Systemcode von 0x10000 nach 0x100000 kopieren.
|
||||
;
|
||||
|
||||
mov ax, 0x10 ; 0x10 entspricht dem Data-Eintrag in der GDT.
|
||||
mov ds, ax ; DS und ES werden von movsd benoetigt.
|
||||
mov es, ax
|
||||
|
||||
xor ecx, ecx ; Anzahl Systemsektoren laden
|
||||
mov cx, [SETUPSEG*0x10+system_sectors]
|
||||
|
||||
imul ecx, SECTORSZ/4
|
||||
|
||||
mov esi, SYSTEMSEG*0x10 ; Hier liegt der Systemcode noch ...
|
||||
mov edi, SYSTEMSTART ; ... und hierhin moechten wir ihn verschieben
|
||||
|
||||
cld ; Nach jedem movsb ESI,EDI inkrementieren
|
||||
rep movsd ; Kopiere 4 Byte von [ESI] nach [EDI] ecx male
|
||||
|
||||
|
||||
;
|
||||
; Sprung in den Startup-Code des Systems
|
||||
;
|
||||
|
||||
jmp dword 0x08:SYSTEMSTART
|
||||
|
||||
error:
|
||||
hlt
|
||||
[BITS 16]
|
||||
; Ab hier wieder Real-Mode Code fuer die Codeteile
|
||||
; vor der Umschaltung in den Protected Mode
|
||||
|
||||
;
|
||||
; empty_8042
|
||||
;
|
||||
; Ein- und Ausgabepuffer des Tastaturcontrollers leeren
|
||||
;
|
||||
empty_8042:
|
||||
call delay
|
||||
in al,0x64 ; 8042 Status Port
|
||||
test al,1 ; Ausgabepuffer voll?
|
||||
jz no_output
|
||||
call delay
|
||||
in al,0x60 ; wenn ja: ueberlesen
|
||||
jmp empty_8042
|
||||
no_output:
|
||||
test al,2 ; Eingabepuffer voll?
|
||||
jnz empty_8042 ; wenn ja, noch mal testen, irgendwann
|
||||
ret ; muss es weg sein.
|
||||
;
|
||||
; delay:
|
||||
;
|
||||
; Kurze Verzoegerung fuer in/out-Befehle
|
||||
;
|
||||
delay:
|
||||
out 0x80,al
|
||||
ret
|
||||
|
||||
;
|
||||
; Datenbereich
|
||||
;
|
||||
[SECTION .data]
|
||||
|
||||
; Meldung
|
||||
|
||||
system_sectors:
|
||||
dw 0
|
||||
|
||||
setupmessage:
|
||||
db 13,10
|
||||
db 'setup active'
|
||||
;
|
||||
; Descriptor-Tabellen
|
||||
;
|
||||
gdt:
|
||||
dw 0,0,0,0 ; NULL Deskriptor
|
||||
|
||||
dw 0xFFFF ; 4Gb - (0x100000*0x1000 = 4Gb)
|
||||
dw 0x0000 ; base address=0
|
||||
dw 0x9A00 ; code read/exec
|
||||
dw 0x00CF ; granularity=4096, 386 (+5th nibble of limit)
|
||||
|
||||
dw 0xFFFF ; 4Gb - (0x100000*0x1000 = 4Gb)
|
||||
dw 0x0000 ; base address=0
|
||||
dw 0x9200 ; data read/write
|
||||
dw 0x00CF ; granularity=4096, 386 (+5th nibble of limit)
|
||||
|
||||
dw 0xFFFF ; 4Gb - (0x100000*0x1000 = 4Gb)
|
||||
dw 0x4000 ; 0x4000 -> base address=0x24000 (siehe BIOS.cc)
|
||||
dw 09A02h ; 0x2 -> base address =0x24000 (siehe BIOS.cc) und code read/exec;
|
||||
dw 0008Fh ; granularity=4096, 16-bit code
|
||||
|
||||
idt_48:
|
||||
dw 0 ; idt limit=0
|
||||
dw 0,0 ; idt base=0L
|
||||
|
||||
gdt_48:
|
||||
dw 0x20 ; GDT Limit=24, 3 GDT Eintraege
|
||||
dd SETUPSEG*0x10+gdt; Physikalische Adresse der GDT
|
324
src/device/bios/BIOS.cc
Normal file
324
src/device/bios/BIOS.cc
Normal file
@ -0,0 +1,324 @@
|
||||
/*****************************************************************************
|
||||
* *
|
||||
* B I O S *
|
||||
* *
|
||||
*---------------------------------------------------------------------------*
|
||||
* Beschreibung: BIOS-Schnittstelle *
|
||||
* *
|
||||
* Autor: Michael Schoettner, 29.11.2018 *
|
||||
*****************************************************************************/
|
||||
|
||||
#include "BIOS.h"
|
||||
#include "kernel/system/Globals.h"
|
||||
|
||||
// 16-Bit Code aufrufen, siehe Konstruktor und Aufruf in startup.asm
|
||||
extern "C" {
|
||||
void bios_call();
|
||||
}
|
||||
|
||||
// in startup.asm im GDT-Eintrag so festgeschrieben!
|
||||
constexpr const unsigned int BIOS16_CODE_MEMORY_START = 0x24000;
|
||||
|
||||
// Parameter fuer BIOS-Aufrufe (Register)
|
||||
constexpr const unsigned int BIOS16_PARAM_BASE = 0x26000;
|
||||
|
||||
// Zeiger auf Speichbereich fuer Parameter fuer BIOS-Aufruf (siehe BIOS.h)
|
||||
BIOScall_params* BC_params = reinterpret_cast<BIOScall_params*>(BIOS16_PARAM_BASE);
|
||||
|
||||
/*****************************************************************************
|
||||
* Methode: BIOS::BIOS *
|
||||
*---------------------------------------------------------------------------*
|
||||
* Beschreibung: Konstruktor. Baut manuell ein 16-Bit Code Segment fuer *
|
||||
* den BIOS-Aufruf. Startadresse dieser Funktion steht *
|
||||
* im 4. GDT-Eintrag (siehe startup.asm). *
|
||||
*****************************************************************************/
|
||||
BIOS::BIOS() {
|
||||
unsigned char* codeAddr = reinterpret_cast<unsigned char*>(BIOS16_CODE_MEMORY_START);
|
||||
|
||||
// mov eax, 25000 (Adresse wohin aktuelles esp gesichert wird)
|
||||
*codeAddr = 0x66;
|
||||
codeAddr++;
|
||||
*codeAddr = 0xB8;
|
||||
codeAddr++;
|
||||
*codeAddr = 0x00;
|
||||
codeAddr++;
|
||||
*codeAddr = 0x50;
|
||||
codeAddr++;
|
||||
*codeAddr = 0x02;
|
||||
codeAddr++;
|
||||
*codeAddr = 0x00;
|
||||
codeAddr++;
|
||||
|
||||
// mov [eax], esp (esp abspeichern)
|
||||
*codeAddr = 0x66;
|
||||
codeAddr++;
|
||||
*codeAddr = 0x67;
|
||||
codeAddr++;
|
||||
*codeAddr = 0x89;
|
||||
codeAddr++;
|
||||
*codeAddr = 0x20;
|
||||
codeAddr++;
|
||||
|
||||
// mov eax,cr0 (cr0 auslesen)
|
||||
*codeAddr = 0x0F;
|
||||
codeAddr++;
|
||||
*codeAddr = 0x20;
|
||||
codeAddr++;
|
||||
*codeAddr = 0xC0;
|
||||
codeAddr++;
|
||||
|
||||
// and eax, 7FFEFFFE (Bitmaske zum Abschlaten des Protected-Mode)
|
||||
*codeAddr = 0x66;
|
||||
codeAddr++;
|
||||
*codeAddr = 0x25;
|
||||
codeAddr++;
|
||||
*codeAddr = 0xFE;
|
||||
codeAddr++;
|
||||
*codeAddr = 0xFF;
|
||||
codeAddr++;
|
||||
*codeAddr = 0xFE;
|
||||
codeAddr++;
|
||||
*codeAddr = 0x7F;
|
||||
codeAddr++;
|
||||
|
||||
// mov cr0, eax (cr0 syetzen um den Protected-Mode auszuschalten)
|
||||
*codeAddr = 0x0F;
|
||||
codeAddr++;
|
||||
*codeAddr = 0x22;
|
||||
codeAddr++;
|
||||
*codeAddr = 0xC0;
|
||||
codeAddr++;
|
||||
|
||||
// jmp 2400:001B Instruktions-Pipeline leeren und Dekodierungseinheit auf 16-Bit code umschalten
|
||||
// Wir springen hier zur naechsten Instruktion (*)
|
||||
// 2400:001B (2400<<4 = 24000 + 1B)
|
||||
*codeAddr = 0xEA;
|
||||
codeAddr++;
|
||||
*codeAddr = 0x1B;
|
||||
codeAddr++;
|
||||
*codeAddr = 0x00;
|
||||
codeAddr++;
|
||||
*codeAddr = 0x00;
|
||||
codeAddr++;
|
||||
*codeAddr = 0x24;
|
||||
codeAddr++;
|
||||
|
||||
// (*) mov dx,2400 (Lade 0x2400 nach dx (fuer Parameter-Zugriff -> BIOS16_PARAM_BAS)
|
||||
*codeAddr = 0xBA;
|
||||
codeAddr++;
|
||||
*codeAddr = 0x00;
|
||||
codeAddr++;
|
||||
*codeAddr = 0x24;
|
||||
codeAddr++;
|
||||
|
||||
// mov ss,dx (Lade Stack-Segment-Register)
|
||||
*codeAddr = 0x8E;
|
||||
codeAddr++;
|
||||
*codeAddr = 0xD2;
|
||||
codeAddr++;
|
||||
|
||||
// mov gs,dx
|
||||
*codeAddr = 0x8E;
|
||||
codeAddr++;
|
||||
*codeAddr = 0xEA;
|
||||
codeAddr++;
|
||||
|
||||
// mov esp,2000 -> BIOS16_PARAM_BASE 0x260000 (= 0x2400:2000)
|
||||
*codeAddr = 0x66;
|
||||
codeAddr++;
|
||||
*codeAddr = 0xBC;
|
||||
codeAddr++;
|
||||
*codeAddr = 0x00;
|
||||
codeAddr++;
|
||||
*codeAddr = 0x20;
|
||||
codeAddr++;
|
||||
*codeAddr = 0x00;
|
||||
codeAddr++;
|
||||
*codeAddr = 0x00;
|
||||
codeAddr++;
|
||||
|
||||
// Register laden (stehen in BIOS16_PARAM_BASE, ab 0x260000)
|
||||
// (pop erhöht die Adressen)
|
||||
|
||||
// pop ds
|
||||
*codeAddr = 0x1F;
|
||||
codeAddr++;
|
||||
|
||||
// pop es
|
||||
*codeAddr = 0x07;
|
||||
codeAddr++;
|
||||
|
||||
// pop fs
|
||||
*codeAddr = 0x0f;
|
||||
codeAddr++;
|
||||
*codeAddr = 0xa1;
|
||||
codeAddr++;
|
||||
|
||||
// pop ax
|
||||
*codeAddr = 0x58;
|
||||
codeAddr++;
|
||||
|
||||
// popad
|
||||
*codeAddr = 0x66;
|
||||
codeAddr++;
|
||||
*codeAddr = 0x61;
|
||||
codeAddr++;
|
||||
|
||||
// int(nr)
|
||||
*codeAddr = 0xCD;
|
||||
codeAddr++; // 'int' Instruktion
|
||||
*codeAddr = 0x00;
|
||||
codeAddr++; // Nummer (wird direkt von BIOS::Int direkt hier reingeschrieben)
|
||||
|
||||
// Register speichern in BIOS16_PARAM_BASE (ab 0x260000)
|
||||
|
||||
// pushad
|
||||
*codeAddr = 0x66;
|
||||
codeAddr++;
|
||||
*codeAddr = 0x60;
|
||||
codeAddr++;
|
||||
|
||||
// pushf
|
||||
*codeAddr = 0x9C;
|
||||
codeAddr++;
|
||||
|
||||
// push fs
|
||||
*codeAddr = 0x0f;
|
||||
codeAddr++;
|
||||
*codeAddr = 0xa0;
|
||||
codeAddr++;
|
||||
|
||||
// push es
|
||||
*codeAddr = 0x06;
|
||||
codeAddr++;
|
||||
|
||||
// push ds
|
||||
*codeAddr = 0x1E;
|
||||
codeAddr++;
|
||||
|
||||
// mov eax,cr0
|
||||
*codeAddr = 0x0F;
|
||||
codeAddr++;
|
||||
*codeAddr = 0x20;
|
||||
codeAddr++;
|
||||
*codeAddr = 0xC0;
|
||||
codeAddr++;
|
||||
|
||||
// or eax, 00010001 (protected mode without paging)
|
||||
*codeAddr = 0x66;
|
||||
codeAddr++;
|
||||
*codeAddr = 0x0D;
|
||||
codeAddr++;
|
||||
*codeAddr = 0x01;
|
||||
codeAddr++;
|
||||
*codeAddr = 0x00;
|
||||
codeAddr++;
|
||||
*codeAddr = 0x01;
|
||||
codeAddr++;
|
||||
*codeAddr = 0x00;
|
||||
codeAddr++;
|
||||
|
||||
// mov cr0, eax
|
||||
*codeAddr = 0x0F;
|
||||
codeAddr++;
|
||||
*codeAddr = 0x22;
|
||||
codeAddr++;
|
||||
*codeAddr = 0xC0;
|
||||
codeAddr++;
|
||||
|
||||
// jmp 0018:0049, flush pipeline & switch decoding (active 32 Bit PM)
|
||||
// 0018:0049
|
||||
*codeAddr = 0xEA;
|
||||
codeAddr++;
|
||||
*codeAddr = 0x49;
|
||||
codeAddr++;
|
||||
*codeAddr = 0x00;
|
||||
codeAddr++;
|
||||
*codeAddr = 0x18;
|
||||
codeAddr++;
|
||||
*codeAddr = 0x00;
|
||||
codeAddr++;
|
||||
|
||||
// mov dx,0010
|
||||
*codeAddr = 0xBA;
|
||||
codeAddr++;
|
||||
*codeAddr = 0x10;
|
||||
codeAddr++;
|
||||
*codeAddr = 0x00;
|
||||
codeAddr++;
|
||||
|
||||
// mov ds,dx
|
||||
*codeAddr = 0x8E;
|
||||
codeAddr++;
|
||||
*codeAddr = 0xDA;
|
||||
codeAddr++;
|
||||
|
||||
// mov es,dx
|
||||
*codeAddr = 0x8E;
|
||||
codeAddr++;
|
||||
*codeAddr = 0xC2;
|
||||
codeAddr++;
|
||||
|
||||
// mov es,dx
|
||||
*codeAddr = 0x8E;
|
||||
codeAddr++;
|
||||
*codeAddr = 0xE2;
|
||||
codeAddr++;
|
||||
|
||||
// mov fs,dx
|
||||
*codeAddr = 0x8E;
|
||||
codeAddr++;
|
||||
*codeAddr = 0xEA;
|
||||
codeAddr++;
|
||||
|
||||
// mov ss,dx
|
||||
*codeAddr = 0x8E;
|
||||
codeAddr++;
|
||||
*codeAddr = 0xD2;
|
||||
codeAddr++;
|
||||
|
||||
// mov eax, 25000
|
||||
*codeAddr = 0x66;
|
||||
codeAddr++;
|
||||
*codeAddr = 0xB8;
|
||||
codeAddr++;
|
||||
*codeAddr = 0x00;
|
||||
codeAddr++;
|
||||
*codeAddr = 0x50;
|
||||
codeAddr++;
|
||||
*codeAddr = 0x02;
|
||||
codeAddr++;
|
||||
*codeAddr = 0x00;
|
||||
codeAddr++;
|
||||
|
||||
// mov esp, [eax]
|
||||
*codeAddr = 0x66;
|
||||
codeAddr++;
|
||||
*codeAddr = 0x67;
|
||||
codeAddr++;
|
||||
*codeAddr = 0x8B;
|
||||
codeAddr++;
|
||||
*codeAddr = 0x20;
|
||||
codeAddr++;
|
||||
|
||||
// far ret
|
||||
*codeAddr = 0x66;
|
||||
codeAddr++;
|
||||
*codeAddr = 0xCB;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* Methode: BIOS::Int *
|
||||
*---------------------------------------------------------------------------*
|
||||
* Beschreibung: Fuehrt einen BIOS-Aufruf per Software-Interrupt durch. *
|
||||
*****************************************************************************/
|
||||
void BIOS::Int(int inter) {
|
||||
unsigned char* ptr = reinterpret_cast<unsigned char*>(BIOS16_CODE_MEMORY_START);
|
||||
|
||||
// Interrupt-Nummer in 16-Bit Code-Segment schreiben (unschoen, aber ...)
|
||||
*(ptr + 48) = static_cast<unsigned char>(inter);
|
||||
|
||||
CPU::disable_int(); // Interrupts abschalten
|
||||
bios_call();
|
||||
CPU::enable_int();
|
||||
}
|
53
src/device/bios/BIOS.h
Normal file
53
src/device/bios/BIOS.h
Normal file
@ -0,0 +1,53 @@
|
||||
/*****************************************************************************
|
||||
* *
|
||||
* B I O S *
|
||||
* *
|
||||
*---------------------------------------------------------------------------*
|
||||
* Beschreibung: Zugriff auf das 16-Bit BIOS. Fuer VESA-Funktionen. *
|
||||
* *
|
||||
* Autor: Michael Schoettner, 13.9.2016 *
|
||||
*****************************************************************************/
|
||||
#ifndef BIOS_include__
|
||||
#define BIOS_include__
|
||||
|
||||
// Speicherseite fuer Rueckgabewerte von BIOS-Aufrufen
|
||||
constexpr const unsigned int RETURN_MEM = 0x9F000;
|
||||
|
||||
// Struktur fuer Parameteruebergabe fuer einen BIOS-Aufruf
|
||||
struct BIOScall_params {
|
||||
unsigned short DS;
|
||||
unsigned short ES;
|
||||
unsigned short FS;
|
||||
unsigned short Flags;
|
||||
unsigned int DI;
|
||||
unsigned int SI;
|
||||
unsigned int BP;
|
||||
unsigned int SP;
|
||||
unsigned int BX;
|
||||
unsigned int DX;
|
||||
unsigned int CX;
|
||||
unsigned int AX;
|
||||
} __attribute__((packed));
|
||||
// kein Auffuellen von bytes auf Wortgrenzen
|
||||
|
||||
// Zeiger auf Speichbereich fuer Parameter fuer BIOS-Aufruf
|
||||
extern BIOScall_params* BC_params;
|
||||
|
||||
class BIOS {
|
||||
private:
|
||||
// Initialisierung: manuelles Anlegen einer Funktion
|
||||
BIOS();
|
||||
|
||||
public:
|
||||
BIOS(const BIOS& copy) = delete; // Verhindere Kopieren
|
||||
|
||||
static BIOS& instance() {
|
||||
static BIOS bios;
|
||||
return bios;
|
||||
}
|
||||
|
||||
// BIOS-Aufruf, per Software-Interrupt
|
||||
static void Int(int inter);
|
||||
};
|
||||
|
||||
#endif
|
52
src/device/cpu/CPU.h
Executable file
52
src/device/cpu/CPU.h
Executable file
@ -0,0 +1,52 @@
|
||||
/*****************************************************************************
|
||||
* *
|
||||
* C P U *
|
||||
* *
|
||||
*---------------------------------------------------------------------------*
|
||||
* Beschreibung: Implementierung einer Abstraktion fuer den Prozessor. *
|
||||
* Derzeit wird nur angeboten, Interrupts zuzulassen, zu *
|
||||
* verbieten oder den Prozessor anzuhalten. *
|
||||
* *
|
||||
* Autor: Michael Schoettner, 30.7.16 *
|
||||
*****************************************************************************/
|
||||
#ifndef CPU_include__
|
||||
#define CPU_include__
|
||||
|
||||
class CPU {
|
||||
public:
|
||||
CPU(const CPU& copy) = delete; // Verhindere Kopieren
|
||||
|
||||
CPU() = default;
|
||||
|
||||
// Erlauben von (Hardware-)Interrupts
|
||||
static inline void enable_int() {
|
||||
asm volatile("sti");
|
||||
}
|
||||
|
||||
// Interrupts werden ignoriert/verboten
|
||||
static inline void disable_int() {
|
||||
asm volatile("cli");
|
||||
}
|
||||
|
||||
// Prozessor bis zum naechsten Interrupt anhalten
|
||||
static inline void idle() {
|
||||
asm volatile("sti;"
|
||||
"hlt");
|
||||
}
|
||||
|
||||
// Prozessor anhalten
|
||||
static inline void halt() {
|
||||
asm volatile("cli;"
|
||||
"hlt");
|
||||
}
|
||||
|
||||
// Time-Stamp-Counter auslesen
|
||||
static inline unsigned long long int rdtsc() {
|
||||
unsigned long long int ret;
|
||||
asm volatile("rdtsc"
|
||||
: "=A"(ret));
|
||||
return ret;
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
201
src/device/graphics/CGA.cc
Executable file
201
src/device/graphics/CGA.cc
Executable file
@ -0,0 +1,201 @@
|
||||
/*****************************************************************************
|
||||
* *
|
||||
* C G A *
|
||||
* *
|
||||
*---------------------------------------------------------------------------*
|
||||
* Beschreibung: Mit Hilfe dieser Klasse kann man auf den Bildschirm des *
|
||||
* PCs zugreifen. Der Zugriff erfolgt direkt auf der Hard- *
|
||||
* wareebene, d.h. ueber den Bildschirmspeicher und den *
|
||||
* I/O-Ports der Grafikkarte. *
|
||||
* *
|
||||
* Autor: Olaf Spinczyk, TU Dortmund *
|
||||
* Aenderungen von Michael Schoettner, HHU, 21.8.2016 *
|
||||
*****************************************************************************/
|
||||
#include "CGA.h"
|
||||
#include "lib/mem/Memory.h"
|
||||
|
||||
const IOport CGA::index_port(0x3d4);
|
||||
const IOport CGA::data_port(0x3d5);
|
||||
|
||||
const bse::span<CGA::cga_char_t, CGA::ROWS * CGA::COLUMNS> CGA::SCREEN{reinterpret_cast<CGA::cga_char_t*>(0xb8000U)};
|
||||
const bse::span<CGA::cga_line_t, CGA::ROWS> CGA::SCREEN_ROWS{reinterpret_cast<CGA::cga_line_t*>(0xb8000U)};
|
||||
CGA::cga_page_t* const CGA::SCREEN_PAGE {reinterpret_cast<CGA::cga_page_t*>(0xb8000U)};
|
||||
|
||||
/*****************************************************************************
|
||||
* Methode: CGA::setpos *
|
||||
*---------------------------------------------------------------------------*
|
||||
* Beschreibung: Setzen des Cursors in Spalte x und Zeile y. *
|
||||
*****************************************************************************/
|
||||
void CGA::setpos(unsigned int x, unsigned int y) {
|
||||
|
||||
/* Hier muess Code eingefuegt werden */
|
||||
|
||||
// NOTE: The cursor addresses positions on screen, not bytes
|
||||
unsigned short pos = x + y * COLUMNS;
|
||||
unsigned char cursor_low = pos & 0xFF;
|
||||
unsigned char cursor_high = (pos >> 8) & 0xFF;
|
||||
|
||||
index_port.outb(0xF); // Cursor(low)
|
||||
data_port.outb(cursor_low);
|
||||
|
||||
index_port.outb(0xE); // Cursor(high)
|
||||
data_port.outb(cursor_high);
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* Methode: CGA::getpos *
|
||||
*---------------------------------------------------------------------------*
|
||||
* Beschreibung: Abfragem der Cursorposition *
|
||||
* *
|
||||
* Rückgabewerte: x und y *
|
||||
*****************************************************************************/
|
||||
void CGA::getpos(unsigned int& x, unsigned int& y) {
|
||||
|
||||
/* Hier muess Code eingefuegt werden */
|
||||
|
||||
index_port.outb(0xF); // Cursor(low)
|
||||
unsigned char cursor_low = data_port.inb();
|
||||
|
||||
index_port.outb(0xE); // Cursor(high)
|
||||
unsigned char cursor_high = data_port.inb();
|
||||
|
||||
unsigned short cursor =
|
||||
(cursor_low & 0xFF) | ((cursor_high << 8) & 0xFF00);
|
||||
|
||||
x = cursor % COLUMNS;
|
||||
y = (cursor / COLUMNS);
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* Methode: CGA::show *
|
||||
*---------------------------------------------------------------------------*
|
||||
* Beschreibung: Anzeige eines Zeichens mit Attribut an einer bestimmten *
|
||||
* Stelle auf dem Bildschirm. *
|
||||
* *
|
||||
* Parameter: *
|
||||
* x,y Position des Zeichens *
|
||||
* character Das auszugebende Zeichen *
|
||||
* attrib Attributbyte fuer das Zeichen *
|
||||
*****************************************************************************/
|
||||
void CGA::show(unsigned int x, unsigned int y, char character, unsigned char attrib) {
|
||||
|
||||
/* Hier muess Code eingefuegt werden */
|
||||
|
||||
if (x >= COLUMNS || y >= ROWS) {
|
||||
// Out of bounds
|
||||
return;
|
||||
}
|
||||
|
||||
cga_char_t* pos = SCREEN[x + y * COLUMNS];
|
||||
pos->cga_char = character;
|
||||
pos->cga_attribute = attrib;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* Methode: CGA::print *
|
||||
*---------------------------------------------------------------------------*
|
||||
* Beschreibung: Anzeige mehrerer Zeichen ab der aktuellen Cursorposition *
|
||||
* '\n' fuer Zeilenvorschub. *
|
||||
* *
|
||||
* Parameter: *
|
||||
* substring Auszugebende Zeichenkette *
|
||||
* n Laenger der Zeichenkette *
|
||||
* attrib Attributbyte fuer alle Zeichen der Zeichenkette *
|
||||
*****************************************************************************/
|
||||
void CGA::print(const bse::string_view string, unsigned char attrib) const {
|
||||
|
||||
/* Hier muess Code eingefuegt werden */
|
||||
|
||||
unsigned int cursor_x = 0;
|
||||
unsigned int cursor_y = 0; // Don't poll registers every stroke
|
||||
getpos(cursor_x, cursor_y);
|
||||
|
||||
for (char current : string) {
|
||||
if (current == '\n') {
|
||||
cursor_x = 0;
|
||||
cursor_y = cursor_y + 1;
|
||||
|
||||
if (cursor_y >= ROWS) {
|
||||
// Bottom of screen reached
|
||||
scrollup();
|
||||
cursor_y = cursor_y - 1;
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (current == '\0') {
|
||||
// Don't need to run to end if null terminated
|
||||
break;
|
||||
}
|
||||
|
||||
show(cursor_x, cursor_y, current, attrib);
|
||||
cursor_x = cursor_x + 1;
|
||||
|
||||
if (cursor_x >= COLUMNS) {
|
||||
// Right of screen reached
|
||||
cursor_x = 0;
|
||||
cursor_y = cursor_y + 1;
|
||||
|
||||
if (cursor_y >= ROWS) {
|
||||
// Bottom of screen reached
|
||||
scrollup();
|
||||
cursor_y = cursor_y - 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
setpos(cursor_x, cursor_y);
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* Methode: CGA::scrollup *
|
||||
*---------------------------------------------------------------------------*
|
||||
* Beschreibung: Verschiebt den Bildschirminhalt um eine Zeile nach oben. *
|
||||
* Die neue Zeile am unteren Bildrand wird mit Leerzeichen *
|
||||
* gefuellt. *
|
||||
*****************************************************************************/
|
||||
void CGA::scrollup() const {
|
||||
|
||||
/* Hier muss Code eingefuegt werden */
|
||||
|
||||
// Move up
|
||||
bse::memcpy<cga_line_t>(SCREEN_ROWS[0], SCREEN_ROWS[1], ROWS - 1);
|
||||
|
||||
// Clear last line
|
||||
bse::zero<cga_line_t>(SCREEN_ROWS[ROWS - 1]);
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* Methode: CGA::clear *
|
||||
*---------------------------------------------------------------------------*
|
||||
* Beschreibung: Lösche den Textbildschirm. *
|
||||
*****************************************************************************/
|
||||
void CGA::clear() {
|
||||
|
||||
/* Hier muess Code eingefuegt werden */
|
||||
|
||||
bse::zero<cga_page_t>(SCREEN_PAGE);
|
||||
setpos(0, 0);
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* Methode: CGA::attribute *
|
||||
*---------------------------------------------------------------------------*
|
||||
* Beschreibung: Hilfsfunktion zur Erzeugung eines Attribut-Bytes aus *
|
||||
* Hintergrund- und Vordergrundfarbe und der Angabe, ob das *
|
||||
* Zeichen blinkend darzustellen ist. *
|
||||
* *
|
||||
* Parameter: *
|
||||
* bg Background color *
|
||||
* fg Foreground color *
|
||||
* blink ywa/no *
|
||||
*****************************************************************************/
|
||||
unsigned char CGA::attribute(CGA::color bg, CGA::color fg, bool blink) {
|
||||
|
||||
/* Hier muess Code eingefuegt werden */
|
||||
|
||||
return static_cast<int>(blink) << 7 // B0000000
|
||||
| (bg & 0x7) << 4 // 0HHH0000 (Hintergrund)
|
||||
| (fg & 0xF); // 0000VVVV (Vordergrund)
|
||||
}
|
108
src/device/graphics/CGA.h
Executable file
108
src/device/graphics/CGA.h
Executable file
@ -0,0 +1,108 @@
|
||||
/*****************************************************************************
|
||||
* *
|
||||
* C G A *
|
||||
* *
|
||||
*---------------------------------------------------------------------------*
|
||||
* Beschreibung: Mit Hilfe dieser Klasse kann man auf den Bildschirm des *
|
||||
* PCs zugreifen. Der Zugriff erfolgt direkt auf der Hard- *
|
||||
* wareebene, d.h. ueber den Bildschirmspeicher und den *
|
||||
* I/O-Ports der Grafikkarte. *
|
||||
* *
|
||||
* Autor: Olaf Spinczyk, TU Dortmund *
|
||||
* Aenderungen von Michael Schoettner, HHU, 21.8.2016 *
|
||||
*****************************************************************************/
|
||||
#ifndef CGA_include_H_
|
||||
#define CGA_include_H_
|
||||
|
||||
#include "device/port/IOport.h"
|
||||
#include "lib/util/Array.h"
|
||||
#include "lib/util/Span.h"
|
||||
#include "lib/util/String.h"
|
||||
#include "lib/util/StringView.h"
|
||||
|
||||
class CGA {
|
||||
private:
|
||||
static const IOport index_port; // Auswahl eines Register der Grafikkarte
|
||||
static const IOport data_port; // Lese-/Schreib-Zugriff auf Register der Grafikk.
|
||||
|
||||
public:
|
||||
// Copy Konstrutkor unterbinden
|
||||
CGA(const CGA& copy) = delete;
|
||||
|
||||
// Konstruktur mit Initialisierung der Ports
|
||||
CGA() {
|
||||
CGA::setpos(0, 0);
|
||||
}
|
||||
|
||||
// virtual ~CGA() = default;
|
||||
|
||||
// Konstanten fuer die moeglichen Farben im Attribut-Byte.
|
||||
typedef enum {
|
||||
BLACK,
|
||||
BLUE,
|
||||
GREEN,
|
||||
CYAN,
|
||||
RED,
|
||||
MAGENTA,
|
||||
BROWN,
|
||||
LIGHT_GREY,
|
||||
DARK_GREY,
|
||||
LIGHT_BLUE,
|
||||
LIGHT_GREEN,
|
||||
LIGHT_CYAN,
|
||||
LIGHT_RED,
|
||||
LIGHT_MAGENTA,
|
||||
YELLOW,
|
||||
WHITE
|
||||
} color;
|
||||
|
||||
// Standardzeichenfarbe
|
||||
enum { STD_ATTR = BLACK << 4 | LIGHT_GREY };
|
||||
|
||||
// Groesse des Bildschirms (25 Zeilen, 80 Spalten)
|
||||
enum { ROWS = 25,
|
||||
COLUMNS = 80 };
|
||||
|
||||
// Easier access to memory (also easier copying of lines/pages etc)
|
||||
struct cga_char_t {
|
||||
char cga_char;
|
||||
unsigned char cga_attribute;
|
||||
};
|
||||
|
||||
struct cga_line_t {
|
||||
// Can use these arrays since they don't have memory overhead (except for the methods that are elsewhere)
|
||||
bse::array<cga_char_t, COLUMNS> cga_line;
|
||||
};
|
||||
|
||||
struct cga_page_t {
|
||||
bse::array<cga_line_t, ROWS> cga_page;
|
||||
};
|
||||
|
||||
static const bse::span<cga_char_t, ROWS * COLUMNS> SCREEN;
|
||||
static const bse::span<cga_line_t, ROWS> SCREEN_ROWS;
|
||||
static cga_page_t* const SCREEN_PAGE; // No span because can't address anything in [0, 1]
|
||||
|
||||
// Setzen des Cursors in Spalte x und Zeile y.
|
||||
static void setpos(unsigned int x, unsigned int y);
|
||||
|
||||
// Abfragen der Cursorpostion
|
||||
static void getpos(unsigned int& x, unsigned int& y) ;
|
||||
|
||||
// Anzeige eines Zeichens mit Attribut an einer bestimmten Stelle
|
||||
static void show(unsigned int x, unsigned int y, char character, unsigned char attrib = STD_ATTR);
|
||||
|
||||
// Anzeige mehrerer Zeichen ab der aktuellen Cursorposition
|
||||
void print(const bse::string_view substring, unsigned char attrib = STD_ATTR) const;
|
||||
|
||||
// Verschiebt den Bildschirminhalt um eine Zeile nach oben.
|
||||
// Neue Zeile am unteren Bildrand mit Leerzeichen fuellen
|
||||
virtual void scrollup() const;
|
||||
|
||||
// Lösche den Textbildschirm
|
||||
virtual void clear();
|
||||
|
||||
// Hilfsfunktion zur Erzeugung eines Attribut-Bytes
|
||||
static unsigned char attribute(CGA::color bg, CGA::color fg, bool blink);
|
||||
};
|
||||
|
||||
#endif
|
41
src/device/graphics/CGA_Stream.cc
Executable file
41
src/device/graphics/CGA_Stream.cc
Executable file
@ -0,0 +1,41 @@
|
||||
/*****************************************************************************
|
||||
* *
|
||||
* C G A _ S T R E A M *
|
||||
* *
|
||||
*---------------------------------------------------------------------------*
|
||||
* Beschreibung: Die Klasse CGA_Stream ermoeglicht die Ausgabe verschied. *
|
||||
* Datentypen als Zeichenketten auf dem CGA-Bildschirm eines*
|
||||
* PCs. Fuer weitergehende Formatierung oder spezielle *
|
||||
* Effekte stehen die Methoden der Klasse CGA_Stream zur *
|
||||
* Verfuegung. *
|
||||
* *
|
||||
* Autor: Olaf Spinczyk, TU Dortmund *
|
||||
* Aenderungen von Michael Schoettner, HHU, 1.8.16 *
|
||||
*****************************************************************************/
|
||||
|
||||
#include "CGA_Stream.h"
|
||||
|
||||
/*****************************************************************************
|
||||
* Methode: CGA_Stream::flush *
|
||||
*---------------------------------------------------------------------------*
|
||||
* Beschreibung: Methode zur Ausgabe des Pufferinhalts der Basisklasse *
|
||||
* StringBuffer. Die Methode wird implizit aufgerufen, *
|
||||
* sobald der Puffer voll ist, kann aber auch explizit *
|
||||
* verwendet werden, um eine Ausgabe zu erzwingen. *
|
||||
*****************************************************************************/
|
||||
void CGA_Stream::flush() {
|
||||
buffer[pos] = '\0'; // I removed the n argument from print so nullterminate the string
|
||||
print(buffer.data(), attribute(color_bg, color_fg, blink)); // print(buffer...) would work syntactically
|
||||
// but the system wouldn't start, as the bse::array
|
||||
// would be implicitly converted to bse::string and
|
||||
// that is dynamically allocated.
|
||||
// print(buffer.data()...) just uses the stack location of
|
||||
// the internal buffer of bse::array
|
||||
|
||||
// Flushing resets attributes
|
||||
blink = false;
|
||||
color_bg = CGA::BLACK;
|
||||
color_fg = CGA::LIGHT_GREY;
|
||||
|
||||
pos = 0;
|
||||
}
|
91
src/device/graphics/CGA_Stream.h
Executable file
91
src/device/graphics/CGA_Stream.h
Executable file
@ -0,0 +1,91 @@
|
||||
/*****************************************************************************
|
||||
* *
|
||||
* C G A _ S T R E A M *
|
||||
* *
|
||||
*---------------------------------------------------------------------------*
|
||||
* Beschreibung: Die Klasse CGA_Stream ermoeglicht die Ausgabe verschied. *
|
||||
* Datentypen als Zeichenketten auf dem CGA-Bildschirm eines*
|
||||
* PCs. Fuer weitergehende Formatierung oder spezielle *
|
||||
* Effekte stehen die Methoden der Klasse CGA zur *
|
||||
* Verfuegung. *
|
||||
* *
|
||||
* Autor: Olaf Spinczyk, TU Dortmund *
|
||||
* Aenderungen von Michael Schoettner, HHU, 06.04.20 *
|
||||
*****************************************************************************/
|
||||
#ifndef CGA_Stream_include_H_
|
||||
#define CGA_Stream_include_H_
|
||||
|
||||
#include "CGA.h"
|
||||
#include "lib/stream/OutStream.h"
|
||||
#include "lib/async/Semaphore.h"
|
||||
|
||||
// Allow for easier stream-like color changing
|
||||
class fgc {
|
||||
public:
|
||||
constexpr fgc(const CGA::color fg) : fg(fg) {}
|
||||
const CGA::color fg;
|
||||
};
|
||||
|
||||
class bgc {
|
||||
public:
|
||||
constexpr bgc(const CGA::color bg) : bg(bg) {}
|
||||
const CGA::color bg;
|
||||
};
|
||||
|
||||
constexpr const fgc white = fgc(CGA::WHITE);
|
||||
constexpr const fgc black = fgc(CGA::BLACK);
|
||||
constexpr const fgc green = fgc(CGA::GREEN);
|
||||
constexpr const fgc red = fgc(CGA::RED);
|
||||
constexpr const fgc lgrey = fgc(CGA::LIGHT_GREY);
|
||||
|
||||
class CGA_Stream : public OutStream, public CGA {
|
||||
private:
|
||||
// Allow for synchronization of output text, needed when running something in parallel to
|
||||
// the PreemptiveThreadDemo for example
|
||||
// NOTE: Should only be used by threads (like the demos) to not lock the system
|
||||
Semaphore sem;
|
||||
|
||||
CGA::color color_fg;
|
||||
CGA::color color_bg;
|
||||
bool blink;
|
||||
|
||||
friend class Logger; // Give access to the color
|
||||
|
||||
public:
|
||||
CGA_Stream(CGA_Stream& copy) = delete; // Verhindere Kopieren
|
||||
|
||||
CGA_Stream() : sem(1), color_fg(CGA::LIGHT_GREY), color_bg(CGA::BLACK), blink(false) {
|
||||
pos = 0;
|
||||
}
|
||||
|
||||
// CAn't make singleton because atexit
|
||||
|
||||
// ~CGA_Stream() override = default;
|
||||
|
||||
void lock() { sem.p(); }
|
||||
void unlock() { sem.v(); }
|
||||
|
||||
// Methode zur Ausgabe des Pufferinhalts der Basisklasse StringBuffer.
|
||||
void flush() override;
|
||||
|
||||
// Change stream color
|
||||
template<typename T>
|
||||
friend T& operator<<(T& os, const fgc& fg) {
|
||||
CGA::color old_bg = os.color_bg;
|
||||
os.flush();
|
||||
os.color_bg = old_bg;
|
||||
os.color_fg = fg.fg;
|
||||
return os;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
friend T& operator<<(T& os, const bgc& bg) {
|
||||
CGA::color old_fg = os.color_fg;
|
||||
os.flush();
|
||||
os.color_fg = old_fg;
|
||||
os.color_bg = bg.bg;
|
||||
return os;
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
4623
src/device/graphics/Font_8x16.h
Normal file
4623
src/device/graphics/Font_8x16.h
Normal file
File diff suppressed because it is too large
Load Diff
2575
src/device/graphics/Font_8x8.h
Normal file
2575
src/device/graphics/Font_8x8.h
Normal file
File diff suppressed because it is too large
Load Diff
264
src/device/graphics/Font_acorn_8x8.h
Normal file
264
src/device/graphics/Font_acorn_8x8.h
Normal file
@ -0,0 +1,264 @@
|
||||
// vim: set et ts=4 sw=4:
|
||||
|
||||
/* Acorn-like font definition, with PC graphics characters */
|
||||
|
||||
constexpr const unsigned char acorndata_8x8[] = {
|
||||
/* 00 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ^@ */
|
||||
/* 01 */ 0x7e, 0x81, 0xa5, 0x81, 0xbd, 0x99, 0x81, 0x7e, /* ^A */
|
||||
/* 02 */ 0x7e, 0xff, 0xbd, 0xff, 0xc3, 0xe7, 0xff, 0x7e, /* ^B */
|
||||
/* 03 */ 0x6c, 0xfe, 0xfe, 0xfe, 0x7c, 0x38, 0x10, 0x00, /* ^C */
|
||||
/* 04 */ 0x10, 0x38, 0x7c, 0xfe, 0x7c, 0x38, 0x10, 0x00, /* ^D */
|
||||
/* 05 */ 0x00, 0x18, 0x3c, 0xe7, 0xe7, 0x3c, 0x18, 0x00, /* ^E */
|
||||
/* 06 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
/* 07 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
/* 08 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
/* 09 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
/* 0A */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
/* 0B */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
/* 0C */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
/* 0D */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
/* 0E */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
/* 0F */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
/* 10 */ 0x00, 0x60, 0x78, 0x7e, 0x7e, 0x78, 0x60, 0x00, /* |> */
|
||||
/* 11 */ 0x00, 0x06, 0x1e, 0x7e, 0x7e, 0x1e, 0x06, 0x00, /* <| */
|
||||
/* 12 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
/* 13 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
/* 14 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
/* 15 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
/* 16 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
/* 17 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
/* 18 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
/* 19 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
/* 1A */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
/* 1B */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
/* 1C */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
/* 1D */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
/* 1E */ 0x00, 0x18, 0x18, 0x3c, 0x3c, 0x7e, 0x7e, 0x00, /* /\ */
|
||||
/* 1F */ 0x00, 0x7e, 0x7e, 0x3c, 0x3c, 0x18, 0x18, 0x00, /* \/ */
|
||||
/* 20 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* */
|
||||
/* 21 */ 0x18, 0x3c, 0x3c, 0x18, 0x18, 0x00, 0x18, 0x00, /* ! */
|
||||
/* 22 */ 0x6C, 0x6C, 0x6C, 0x00, 0x00, 0x00, 0x00, 0x00, /* " */
|
||||
/* 23 */ 0x36, 0x36, 0x7F, 0x36, 0x7F, 0x36, 0x36, 0x00, /* # */
|
||||
/* 24 */ 0x0C, 0x3F, 0x68, 0x3E, 0x0B, 0x7E, 0x18, 0x00, /* $ */
|
||||
/* 25 */ 0x60, 0x66, 0x0C, 0x18, 0x30, 0x66, 0x06, 0x00, /* % */
|
||||
/* 26 */ 0x38, 0x6C, 0x6C, 0x38, 0x6D, 0x66, 0x3B, 0x00, /* & */
|
||||
/* 27 */ 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, /* ' */
|
||||
/* 28 */ 0x0C, 0x18, 0x30, 0x30, 0x30, 0x18, 0x0C, 0x00, /* ( */
|
||||
/* 29 */ 0x30, 0x18, 0x0C, 0x0C, 0x0C, 0x18, 0x30, 0x00, /* ) */
|
||||
/* 2A */ 0x00, 0x18, 0x7E, 0x3C, 0x7E, 0x18, 0x00, 0x00, /* * */
|
||||
/* 2B */ 0x00, 0x18, 0x18, 0x7E, 0x18, 0x18, 0x00, 0x00, /* + */
|
||||
/* 2C */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x30, /* , */
|
||||
/* 2D */ 0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x00, /* - */
|
||||
/* 2E */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, /* . */
|
||||
/* 2F */ 0x00, 0x06, 0x0C, 0x18, 0x30, 0x60, 0x00, 0x00, /* / */
|
||||
/* 30 */ 0x3C, 0x66, 0x6E, 0x7E, 0x76, 0x66, 0x3C, 0x00, /* 0 */
|
||||
/* 31 */ 0x18, 0x38, 0x18, 0x18, 0x18, 0x18, 0x7E, 0x00, /* 1 */
|
||||
/* 32 */ 0x3C, 0x66, 0x06, 0x0C, 0x18, 0x30, 0x7E, 0x00, /* 2 */
|
||||
/* 33 */ 0x3C, 0x66, 0x06, 0x1C, 0x06, 0x66, 0x3C, 0x00, /* 3 */
|
||||
/* 34 */ 0x0C, 0x1C, 0x3C, 0x6C, 0x7E, 0x0C, 0x0C, 0x00, /* 4 */
|
||||
/* 35 */ 0x7E, 0x60, 0x7C, 0x06, 0x06, 0x66, 0x3C, 0x00, /* 5 */
|
||||
/* 36 */ 0x1C, 0x30, 0x60, 0x7C, 0x66, 0x66, 0x3C, 0x00, /* 6 */
|
||||
/* 37 */ 0x7E, 0x06, 0x0C, 0x18, 0x30, 0x30, 0x30, 0x00, /* 7 */
|
||||
/* 38 */ 0x3C, 0x66, 0x66, 0x3C, 0x66, 0x66, 0x3C, 0x00, /* 8 */
|
||||
/* 39 */ 0x3C, 0x66, 0x66, 0x3E, 0x06, 0x0C, 0x38, 0x00, /* 9 */
|
||||
/* 3A */ 0x00, 0x00, 0x18, 0x18, 0x00, 0x18, 0x18, 0x00, /* : */
|
||||
/* 3B */ 0x00, 0x00, 0x18, 0x18, 0x00, 0x18, 0x18, 0x30, /* ; */
|
||||
/* 3C */ 0x0C, 0x18, 0x30, 0x60, 0x30, 0x18, 0x0C, 0x00, /* < */
|
||||
/* 3D */ 0x00, 0x00, 0x7E, 0x00, 0x7E, 0x00, 0x00, 0x00, /* = */
|
||||
/* 3E */ 0x30, 0x18, 0x0C, 0x06, 0x0C, 0x18, 0x30, 0x00, /* > */
|
||||
/* 3F */ 0x3C, 0x66, 0x0C, 0x18, 0x18, 0x00, 0x18, 0x00, /* ? */
|
||||
/* 40 */ 0x3C, 0x66, 0x6E, 0x6A, 0x6E, 0x60, 0x3C, 0x00, /* @ */
|
||||
/* 41 */ 0x3C, 0x66, 0x66, 0x7E, 0x66, 0x66, 0x66, 0x00, /* A */
|
||||
/* 42 */ 0x7C, 0x66, 0x66, 0x7C, 0x66, 0x66, 0x7C, 0x00, /* B */
|
||||
/* 43 */ 0x3C, 0x66, 0x60, 0x60, 0x60, 0x66, 0x3C, 0x00, /* C */
|
||||
/* 44 */ 0x78, 0x6C, 0x66, 0x66, 0x66, 0x6C, 0x78, 0x00, /* D */
|
||||
/* 45 */ 0x7E, 0x60, 0x60, 0x7C, 0x60, 0x60, 0x7E, 0x00, /* E */
|
||||
/* 46 */ 0x7E, 0x60, 0x60, 0x7C, 0x60, 0x60, 0x60, 0x00, /* F */
|
||||
/* 47 */ 0x3C, 0x66, 0x60, 0x6E, 0x66, 0x66, 0x3C, 0x00, /* G */
|
||||
/* 48 */ 0x66, 0x66, 0x66, 0x7E, 0x66, 0x66, 0x66, 0x00, /* H */
|
||||
/* 49 */ 0x7E, 0x18, 0x18, 0x18, 0x18, 0x18, 0x7E, 0x00, /* I */
|
||||
/* 4A */ 0x3E, 0x0C, 0x0C, 0x0C, 0x0C, 0x6C, 0x38, 0x00, /* J */
|
||||
/* 4B */ 0x66, 0x6C, 0x78, 0x70, 0x78, 0x6C, 0x66, 0x00, /* K */
|
||||
/* 4C */ 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x7E, 0x00, /* L */
|
||||
/* 4D */ 0x63, 0x77, 0x7F, 0x6B, 0x6B, 0x63, 0x63, 0x00, /* M */
|
||||
/* 4E */ 0x66, 0x66, 0x76, 0x7E, 0x6E, 0x66, 0x66, 0x00, /* N */
|
||||
/* 4F */ 0x3C, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3C, 0x00, /* O */
|
||||
/* 50 */ 0x7C, 0x66, 0x66, 0x7C, 0x60, 0x60, 0x60, 0x00, /* P */
|
||||
/* 51 */ 0x3C, 0x66, 0x66, 0x66, 0x6A, 0x6C, 0x36, 0x00, /* Q */
|
||||
/* 52 */ 0x7C, 0x66, 0x66, 0x7C, 0x6C, 0x66, 0x66, 0x00, /* R */
|
||||
/* 53 */ 0x3C, 0x66, 0x60, 0x3C, 0x06, 0x66, 0x3C, 0x00, /* S */
|
||||
/* 54 */ 0x7E, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, /* T */
|
||||
/* 55 */ 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3C, 0x00, /* U */
|
||||
/* 56 */ 0x66, 0x66, 0x66, 0x66, 0x66, 0x3C, 0x18, 0x00, /* V */
|
||||
/* 57 */ 0x63, 0x63, 0x6B, 0x6B, 0x7F, 0x77, 0x63, 0x00, /* W */
|
||||
/* 58 */ 0x66, 0x66, 0x3C, 0x18, 0x3C, 0x66, 0x66, 0x00, /* X */
|
||||
/* 59 */ 0x66, 0x66, 0x66, 0x3C, 0x18, 0x18, 0x18, 0x00, /* Y */
|
||||
/* 5A */ 0x7E, 0x06, 0x0C, 0x18, 0x30, 0x60, 0x7E, 0x00, /* Z */
|
||||
/* 5B */ 0x7C, 0x60, 0x60, 0x60, 0x60, 0x60, 0x7C, 0x00, /* [ */
|
||||
/* 5C */ 0x00, 0x60, 0x30, 0x18, 0x0C, 0x06, 0x00, 0x00, /* \ */
|
||||
/* 5D */ 0x3E, 0x06, 0x06, 0x06, 0x06, 0x06, 0x3E, 0x00, /* ] */
|
||||
/* 5E */ 0x3C, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ^ */
|
||||
/* 5F */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, /* _ */
|
||||
/* 60 */ 0x30, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* */
|
||||
/* 61 */ 0x00, 0x00, 0x3C, 0x06, 0x3E, 0x66, 0x3E, 0x00, /* a */
|
||||
/* 62 */ 0x60, 0x60, 0x7C, 0x66, 0x66, 0x66, 0x7C, 0x00, /* b */
|
||||
/* 63 */ 0x00, 0x00, 0x3C, 0x66, 0x60, 0x66, 0x3C, 0x00, /* c */
|
||||
/* 64 */ 0x06, 0x06, 0x3E, 0x66, 0x66, 0x66, 0x3E, 0x00, /* d */
|
||||
/* 65 */ 0x00, 0x00, 0x3C, 0x66, 0x7E, 0x60, 0x3C, 0x00, /* e */
|
||||
/* 66 */ 0x1C, 0x30, 0x30, 0x7C, 0x30, 0x30, 0x30, 0x00, /* f */
|
||||
/* 67 */ 0x00, 0x00, 0x3E, 0x66, 0x66, 0x3E, 0x06, 0x3C, /* g */
|
||||
/* 68 */ 0x60, 0x60, 0x7C, 0x66, 0x66, 0x66, 0x66, 0x00, /* h */
|
||||
/* 69 */ 0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x3C, 0x00, /* i */
|
||||
/* 6A */ 0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x70, /* j */
|
||||
/* 6B */ 0x60, 0x60, 0x66, 0x6C, 0x78, 0x6C, 0x66, 0x00, /* k */
|
||||
/* 6C */ 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3C, 0x00, /* l */
|
||||
/* 6D */ 0x00, 0x00, 0x36, 0x7F, 0x6B, 0x6B, 0x63, 0x00, /* m */
|
||||
/* 6E */ 0x00, 0x00, 0x7C, 0x66, 0x66, 0x66, 0x66, 0x00, /* n */
|
||||
/* 6F */ 0x00, 0x00, 0x3C, 0x66, 0x66, 0x66, 0x3C, 0x00, /* o */
|
||||
/* 70 */ 0x00, 0x00, 0x7C, 0x66, 0x66, 0x7C, 0x60, 0x60, /* p */
|
||||
/* 71 */ 0x00, 0x00, 0x3E, 0x66, 0x66, 0x3E, 0x06, 0x07, /* q */
|
||||
/* 72 */ 0x00, 0x00, 0x6C, 0x76, 0x60, 0x60, 0x60, 0x00, /* r */
|
||||
/* 73 */ 0x00, 0x00, 0x3E, 0x60, 0x3C, 0x06, 0x7C, 0x00, /* s */
|
||||
/* 74 */ 0x30, 0x30, 0x7C, 0x30, 0x30, 0x30, 0x1C, 0x00, /* t */
|
||||
/* 75 */ 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x3E, 0x00, /* u */
|
||||
/* 76 */ 0x00, 0x00, 0x66, 0x66, 0x66, 0x3C, 0x18, 0x00, /* v */
|
||||
/* 77 */ 0x00, 0x00, 0x63, 0x6B, 0x6B, 0x7F, 0x36, 0x00, /* w */
|
||||
/* 78 */ 0x00, 0x00, 0x66, 0x3C, 0x18, 0x3C, 0x66, 0x00, /* x */
|
||||
/* 79 */ 0x00, 0x00, 0x66, 0x66, 0x66, 0x3E, 0x06, 0x3C, /* y */
|
||||
/* 7A */ 0x00, 0x00, 0x7E, 0x0C, 0x18, 0x30, 0x7E, 0x00, /* z */
|
||||
/* 7B */ 0x0C, 0x18, 0x18, 0x70, 0x18, 0x18, 0x0C, 0x00, /* { */
|
||||
/* 7C */ 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, /* | */
|
||||
/* 7D */ 0x30, 0x18, 0x18, 0x0E, 0x18, 0x18, 0x30, 0x00, /* } */
|
||||
/* 7E */ 0x31, 0x6B, 0x46, 0x00, 0x00, 0x00, 0x00, 0x00, /* ~ */
|
||||
/* 7F */ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, /* */
|
||||
/* 80 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
/* 81 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
/* 82 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
/* 83 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
/* 84 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
/* 85 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
/* 86 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
/* 87 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
/* 88 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
/* 89 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
/* 8A */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
/* 8B */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
/* 8C */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
/* 8D */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
/* 8E */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
/* 8F */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
/* 90 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
/* 91 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
/* 92 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
/* 93 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
/* 94 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
/* 95 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
/* 96 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
/* 97 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
/* 98 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
/* 99 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
/* 9A */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
/* 9B */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
/* 9C */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
/* 9D */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
/* 9E */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
/* 9F */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
/* A0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
/* A1 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
/* A2 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
/* A3 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
/* A4 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
/* A5 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
/* A6 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
/* A7 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
/* A8 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
/* A9 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
/* AA */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
/* AB */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
/* AC */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
/* AD */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
/* AE */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
/* AF */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
/* B0 */ 0x22, 0x88, 0x22, 0x88, 0x22, 0x88, 0x22, 0x88,
|
||||
/* B1 */ 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa,
|
||||
/* B2 */ 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77,
|
||||
/* B3 */ 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
|
||||
/* B4 */ 0x18, 0x18, 0x18, 0xf8, 0x18, 0x18, 0x18, 0x18,
|
||||
/* B5 */ 0x18, 0x18, 0xf8, 0x18, 0xf8, 0x18, 0x18, 0x18,
|
||||
/* B6 */ 0x66, 0x66, 0x66, 0xe6, 0x66, 0x66, 0x66, 0x66,
|
||||
/* B7 */ 0x00, 0x00, 0x00, 0xfe, 0x66, 0x66, 0x66, 0x66,
|
||||
/* B8 */ 0x00, 0x00, 0xf8, 0x18, 0xf8, 0x18, 0x18, 0x18,
|
||||
/* B9 */ 0x66, 0x66, 0xe6, 0x06, 0xe6, 0x66, 0x66, 0x66,
|
||||
/* BA */ 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
|
||||
/* BB */ 0x00, 0x00, 0xfe, 0x06, 0xe6, 0x66, 0x66, 0x66,
|
||||
/* BC */ 0x66, 0x66, 0xe6, 0x06, 0xfe, 0x00, 0x00, 0x00,
|
||||
/* BD */ 0x66, 0x66, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00,
|
||||
/* BE */ 0x18, 0x18, 0xf8, 0x18, 0xf8, 0x00, 0x00, 0x00,
|
||||
/* BF */ 0x00, 0x00, 0x00, 0xf8, 0x18, 0x18, 0x18, 0x18,
|
||||
/* C0 */ 0x18, 0x18, 0x18, 0x1f, 0x00, 0x00, 0x00, 0x00,
|
||||
/* C1 */ 0x18, 0x18, 0x18, 0xff, 0x00, 0x00, 0x00, 0x00,
|
||||
/* C2 */ 0x00, 0x00, 0x00, 0xff, 0x18, 0x18, 0x18, 0x18,
|
||||
/* C3 */ 0x18, 0x18, 0x18, 0x1f, 0x18, 0x18, 0x18, 0x18,
|
||||
/* C4 */ 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00,
|
||||
/* C5 */ 0x18, 0x18, 0x18, 0xff, 0x18, 0x18, 0x18, 0x18,
|
||||
/* C6 */ 0x18, 0x18, 0x1f, 0x18, 0x1f, 0x18, 0x18, 0x18,
|
||||
/* C7 */ 0x66, 0x66, 0x66, 0x67, 0x66, 0x66, 0x66, 0x66,
|
||||
/* C8 */ 0x66, 0x66, 0x67, 0x60, 0x7f, 0x00, 0x00, 0x00,
|
||||
/* C9 */ 0x00, 0x00, 0x7f, 0x60, 0x67, 0x66, 0x66, 0x66,
|
||||
/* CA */ 0x66, 0x66, 0xe7, 0x00, 0xff, 0x00, 0x00, 0x00,
|
||||
/* CB */ 0x00, 0x00, 0xff, 0x00, 0xe7, 0x66, 0x66, 0x66,
|
||||
/* CC */ 0x66, 0x66, 0x67, 0x60, 0x67, 0x66, 0x66, 0x66,
|
||||
/* CD */ 0x00, 0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00,
|
||||
/* CE */ 0x66, 0x66, 0xe7, 0x00, 0xe7, 0x66, 0x66, 0x66,
|
||||
/* CF */ 0x18, 0x18, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00,
|
||||
/* D0 */ 0x66, 0x66, 0x66, 0xff, 0x00, 0x00, 0x00, 0x00,
|
||||
/* D1 */ 0x00, 0x00, 0xff, 0x00, 0xff, 0x18, 0x18, 0x18,
|
||||
/* D2 */ 0x00, 0x00, 0x00, 0xff, 0x66, 0x66, 0x66, 0x66,
|
||||
/* D3 */ 0x66, 0x66, 0x66, 0x7f, 0x00, 0x00, 0x00, 0x00,
|
||||
/* D4 */ 0x18, 0x18, 0x1f, 0x18, 0x1f, 0x00, 0x00, 0x00,
|
||||
/* D5 */ 0x00, 0x00, 0x1f, 0x18, 0x1f, 0x18, 0x18, 0x18,
|
||||
/* D6 */ 0x00, 0x00, 0x00, 0x7f, 0x66, 0x66, 0x66, 0x66,
|
||||
/* D7 */ 0x66, 0x66, 0x66, 0xff, 0x66, 0x66, 0x66, 0x66,
|
||||
/* D8 */ 0x18, 0x18, 0xff, 0x18, 0xff, 0x18, 0x18, 0x18,
|
||||
/* D9 */ 0x18, 0x18, 0x18, 0xf8, 0x00, 0x00, 0x00, 0x00,
|
||||
/* DA */ 0x00, 0x00, 0x00, 0x1f, 0x18, 0x18, 0x18, 0x18,
|
||||
/* DB */ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
/* DC */ 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
|
||||
/* DD */ 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0,
|
||||
/* DE */ 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f,
|
||||
/* DF */ 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
|
||||
/* E0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
/* E1 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
/* E2 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
/* E3 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
/* E4 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
/* E5 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
/* E6 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
/* E7 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
/* E8 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
/* E9 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
/* EA */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
/* EB */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
/* EC */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
/* ED */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
/* EE */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
/* EF */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
/* F0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
/* F1 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
/* F2 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
/* F3 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
/* F4 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
/* F5 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
/* F6 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
/* F7 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
/* F8 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
/* F9 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
/* FA */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
/* FB */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
/* FC */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
/* FD */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
/* FE */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
/* FF */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
};
|
||||
|
||||
#undef FONTDATAMAX
|
2580
src/device/graphics/Font_pearl_8x8.h
Normal file
2580
src/device/graphics/Font_pearl_8x8.h
Normal file
File diff suppressed because it is too large
Load Diff
6208
src/device/graphics/Font_sun_12x22.h
Normal file
6208
src/device/graphics/Font_sun_12x22.h
Normal file
File diff suppressed because it is too large
Load Diff
265
src/device/graphics/Font_sun_8x16.h
Normal file
265
src/device/graphics/Font_sun_8x16.h
Normal file
@ -0,0 +1,265 @@
|
||||
// vim: set et ts=4 sw=4:
|
||||
|
||||
constexpr const unsigned int FONTDATAMAX_SUN8x16 = 4096;
|
||||
|
||||
constexpr const unsigned char fontdata_sun_8x16[FONTDATAMAX_SUN8x16] = {
|
||||
/* */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
/* */ 0x00,0x00,0x7e,0x81,0xa5,0x81,0x81,0xbd,0x99,0x81,0x81,0x7e,0x00,0x00,0x00,0x00,
|
||||
/* */ 0x00,0x00,0x7e,0xff,0xdb,0xff,0xff,0xc3,0xe7,0xff,0xff,0x7e,0x00,0x00,0x00,0x00,
|
||||
/* */ 0x00,0x00,0x00,0x00,0x6c,0xfe,0xfe,0xfe,0xfe,0x7c,0x38,0x10,0x00,0x00,0x00,0x00,
|
||||
/* */ 0x00,0x00,0x00,0x00,0x10,0x38,0x7c,0xfe,0x7c,0x38,0x10,0x00,0x00,0x00,0x00,0x00,
|
||||
/* */ 0x00,0x00,0x00,0x18,0x3c,0x3c,0xe7,0xe7,0xe7,0x18,0x18,0x3c,0x00,0x00,0x00,0x00,
|
||||
/* */ 0x00,0x00,0x00,0x18,0x3c,0x7e,0xff,0xff,0x7e,0x18,0x18,0x3c,0x00,0x00,0x00,0x00,
|
||||
/* */ 0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x3c,0x3c,0x18,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
/* */ 0xff,0xff,0xff,0xff,0xff,0xff,0xe7,0xc3,0xc3,0xe7,0xff,0xff,0xff,0xff,0xff,0xff,
|
||||
/* */ 0x00,0x00,0x00,0x00,0x00,0x3c,0x66,0x42,0x42,0x66,0x3c,0x00,0x00,0x00,0x00,0x00,
|
||||
/* */ 0xff,0xff,0xff,0xff,0xff,0xc3,0x99,0xbd,0xbd,0x99,0xc3,0xff,0xff,0xff,0xff,0xff,
|
||||
/* */ 0x00,0x00,0x1e,0x0e,0x1a,0x32,0x78,0xcc,0xcc,0xcc,0xcc,0x78,0x00,0x00,0x00,0x00,
|
||||
/* */ 0x00,0x00,0x3c,0x66,0x66,0x66,0x66,0x3c,0x18,0x7e,0x18,0x18,0x00,0x00,0x00,0x00,
|
||||
/* */ 0x00,0x00,0x3f,0x33,0x3f,0x30,0x30,0x30,0x30,0x70,0xf0,0xe0,0x00,0x00,0x00,0x00,
|
||||
/* */ 0x00,0x00,0x7f,0x63,0x7f,0x63,0x63,0x63,0x63,0x67,0xe7,0xe6,0xc0,0x00,0x00,0x00,
|
||||
/* */ 0x00,0x00,0x00,0x18,0x18,0xdb,0x3c,0xe7,0x3c,0xdb,0x18,0x18,0x00,0x00,0x00,0x00,
|
||||
/* */ 0x00,0x80,0xc0,0xe0,0xf0,0xf8,0xfe,0xf8,0xf0,0xe0,0xc0,0x80,0x00,0x00,0x00,0x00,
|
||||
/* */ 0x00,0x02,0x06,0x0e,0x1e,0x3e,0xfe,0x3e,0x1e,0x0e,0x06,0x02,0x00,0x00,0x00,0x00,
|
||||
/* */ 0x00,0x00,0x18,0x3c,0x7e,0x18,0x18,0x18,0x7e,0x3c,0x18,0x00,0x00,0x00,0x00,0x00,
|
||||
/* */ 0x00,0x00,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x00,0x66,0x66,0x00,0x00,0x00,0x00,
|
||||
/* */ 0x00,0x00,0x7f,0xdb,0xdb,0xdb,0x7b,0x1b,0x1b,0x1b,0x1b,0x1b,0x00,0x00,0x00,0x00,
|
||||
/* */ 0x00,0x7c,0xc6,0x60,0x38,0x6c,0xc6,0xc6,0x6c,0x38,0x0c,0xc6,0x7c,0x00,0x00,0x00,
|
||||
/* */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfe,0xfe,0xfe,0xfe,0x00,0x00,0x00,0x00,
|
||||
/* */ 0x00,0x00,0x18,0x3c,0x7e,0x18,0x18,0x18,0x7e,0x3c,0x18,0x7e,0x00,0x00,0x00,0x00,
|
||||
/* */ 0x00,0x00,0x18,0x3c,0x7e,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x00,0x00,0x00,0x00,
|
||||
/* */ 0x00,0x00,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x7e,0x3c,0x18,0x00,0x00,0x00,0x00,
|
||||
/* */ 0x00,0x00,0x00,0x00,0x00,0x18,0x0c,0xfe,0x0c,0x18,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
/* */ 0x00,0x00,0x00,0x00,0x00,0x30,0x60,0xfe,0x60,0x30,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
/* */ 0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0xc0,0xc0,0xfe,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
/* */ 0x00,0x00,0x00,0x00,0x00,0x24,0x66,0xff,0x66,0x24,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
/* */ 0x00,0x00,0x00,0x00,0x10,0x38,0x38,0x7c,0x7c,0xfe,0xfe,0x00,0x00,0x00,0x00,0x00,
|
||||
/* */ 0x00,0x00,0x00,0x00,0xfe,0xfe,0x7c,0x7c,0x38,0x38,0x10,0x00,0x00,0x00,0x00,0x00,
|
||||
/* */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
/*!*/ 0x00,0x00,0x18,0x3c,0x3c,0x3c,0x18,0x18,0x18,0x00,0x18,0x18,0x00,0x00,0x00,0x00,
|
||||
/*"*/ 0x00,0x66,0x66,0x66,0x24,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
/*#*/ 0x00,0x00,0x00,0x6c,0x6c,0xfe,0x6c,0x6c,0x6c,0xfe,0x6c,0x6c,0x00,0x00,0x00,0x00,
|
||||
/*$*/ 0x18,0x18,0x7c,0xc6,0xc2,0xc0,0x7c,0x06,0x06,0x86,0xc6,0x7c,0x18,0x18,0x00,0x00,
|
||||
/*%*/ 0x00,0x00,0x00,0x00,0xc2,0xc6,0x0c,0x18,0x30,0x60,0xc6,0x86,0x00,0x00,0x00,0x00,
|
||||
/*&*/ 0x00,0x00,0x38,0x6c,0x6c,0x38,0x76,0xdc,0xcc,0xcc,0xcc,0x76,0x00,0x00,0x00,0x00,
|
||||
/*'*/ 0x00,0x30,0x30,0x30,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
/*(*/ 0x00,0x00,0x0c,0x18,0x30,0x30,0x30,0x30,0x30,0x30,0x18,0x0c,0x00,0x00,0x00,0x00,
|
||||
/*)*/ 0x00,0x00,0x30,0x18,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x18,0x30,0x00,0x00,0x00,0x00,
|
||||
/***/ 0x00,0x00,0x00,0x00,0x00,0x66,0x3c,0xff,0x3c,0x66,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
/*+*/ 0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x7e,0x18,0x18,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
/*,*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x18,0x30,0x00,0x00,0x00,
|
||||
/*-*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
/*.*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x00,
|
||||
/* */ 0x00,0x00,0x00,0x00,0x02,0x06,0x0c,0x18,0x30,0x60,0xc0,0x80,0x00,0x00,0x00,0x00,
|
||||
/*0*/ 0x00,0x00,0x7c,0xc6,0xc6,0xce,0xde,0xf6,0xe6,0xc6,0xc6,0x7c,0x00,0x00,0x00,0x00,
|
||||
/*1*/ 0x00,0x00,0x18,0x38,0x78,0x18,0x18,0x18,0x18,0x18,0x18,0x7e,0x00,0x00,0x00,0x00,
|
||||
/*2*/ 0x00,0x00,0x7c,0xc6,0x06,0x0c,0x18,0x30,0x60,0xc0,0xc6,0xfe,0x00,0x00,0x00,0x00,
|
||||
/*3*/ 0x00,0x00,0x7c,0xc6,0x06,0x06,0x3c,0x06,0x06,0x06,0xc6,0x7c,0x00,0x00,0x00,0x00,
|
||||
/*4*/ 0x00,0x00,0x0c,0x1c,0x3c,0x6c,0xcc,0xfe,0x0c,0x0c,0x0c,0x1e,0x00,0x00,0x00,0x00,
|
||||
/*5*/ 0x00,0x00,0xfe,0xc0,0xc0,0xc0,0xfc,0x06,0x06,0x06,0xc6,0x7c,0x00,0x00,0x00,0x00,
|
||||
/*6*/ 0x00,0x00,0x38,0x60,0xc0,0xc0,0xfc,0xc6,0xc6,0xc6,0xc6,0x7c,0x00,0x00,0x00,0x00,
|
||||
/*7*/ 0x00,0x00,0xfe,0xc6,0x06,0x06,0x0c,0x18,0x30,0x30,0x30,0x30,0x00,0x00,0x00,0x00,
|
||||
/*8*/ 0x00,0x00,0x7c,0xc6,0xc6,0xc6,0x7c,0xc6,0xc6,0xc6,0xc6,0x7c,0x00,0x00,0x00,0x00,
|
||||
/*9*/ 0x00,0x00,0x7c,0xc6,0xc6,0xc6,0x7e,0x06,0x06,0x06,0x0c,0x78,0x00,0x00,0x00,0x00,
|
||||
/*:*/ 0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x00,0x00,
|
||||
/*;*/ 0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x18,0x18,0x30,0x00,0x00,0x00,0x00,
|
||||
/*<*/ 0x00,0x00,0x00,0x06,0x0c,0x18,0x30,0x60,0x30,0x18,0x0c,0x06,0x00,0x00,0x00,0x00,
|
||||
/*=*/ 0x00,0x00,0x00,0x00,0x00,0x7e,0x00,0x00,0x7e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
/*>*/ 0x00,0x00,0x00,0x60,0x30,0x18,0x0c,0x06,0x0c,0x18,0x30,0x60,0x00,0x00,0x00,0x00,
|
||||
/*?*/ 0x00,0x00,0x7c,0xc6,0xc6,0x0c,0x18,0x18,0x18,0x00,0x18,0x18,0x00,0x00,0x00,0x00,
|
||||
/*@*/ 0x00,0x00,0x7c,0xc6,0xc6,0xc6,0xde,0xde,0xde,0xdc,0xc0,0x7c,0x00,0x00,0x00,0x00,
|
||||
/*A*/ 0x00,0x00,0x10,0x38,0x6c,0xc6,0xc6,0xfe,0xc6,0xc6,0xc6,0xc6,0x00,0x00,0x00,0x00,
|
||||
/*B*/ 0x00,0x00,0xfc,0x66,0x66,0x66,0x7c,0x66,0x66,0x66,0x66,0xfc,0x00,0x00,0x00,0x00,
|
||||
/*C*/ 0x00,0x00,0x3c,0x66,0xc2,0xc0,0xc0,0xc0,0xc0,0xc2,0x66,0x3c,0x00,0x00,0x00,0x00,
|
||||
/*D*/ 0x00,0x00,0xf8,0x6c,0x66,0x66,0x66,0x66,0x66,0x66,0x6c,0xf8,0x00,0x00,0x00,0x00,
|
||||
/*E*/ 0x00,0x00,0xfe,0x66,0x62,0x68,0x78,0x68,0x60,0x62,0x66,0xfe,0x00,0x00,0x00,0x00,
|
||||
/*F*/ 0x00,0x00,0xfe,0x66,0x62,0x68,0x78,0x68,0x60,0x60,0x60,0xf0,0x00,0x00,0x00,0x00,
|
||||
/*G*/ 0x00,0x00,0x3c,0x66,0xc2,0xc0,0xc0,0xde,0xc6,0xc6,0x66,0x3a,0x00,0x00,0x00,0x00,
|
||||
/*H*/ 0x00,0x00,0xc6,0xc6,0xc6,0xc6,0xfe,0xc6,0xc6,0xc6,0xc6,0xc6,0x00,0x00,0x00,0x00,
|
||||
/*I*/ 0x00,0x00,0x3c,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x3c,0x00,0x00,0x00,0x00,
|
||||
/*J*/ 0x00,0x00,0x1e,0x0c,0x0c,0x0c,0x0c,0x0c,0xcc,0xcc,0xcc,0x78,0x00,0x00,0x00,0x00,
|
||||
/*K*/ 0x00,0x00,0xe6,0x66,0x66,0x6c,0x78,0x78,0x6c,0x66,0x66,0xe6,0x00,0x00,0x00,0x00,
|
||||
/*L*/ 0x00,0x00,0xf0,0x60,0x60,0x60,0x60,0x60,0x60,0x62,0x66,0xfe,0x00,0x00,0x00,0x00,
|
||||
/*M*/ 0x00,0x00,0xc3,0xe7,0xff,0xff,0xdb,0xc3,0xc3,0xc3,0xc3,0xc3,0x00,0x00,0x00,0x00,
|
||||
/*N*/ 0x00,0x00,0xc6,0xe6,0xf6,0xfe,0xde,0xce,0xc6,0xc6,0xc6,0xc6,0x00,0x00,0x00,0x00,
|
||||
/*O*/ 0x00,0x00,0x7c,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0x7c,0x00,0x00,0x00,0x00,
|
||||
/*P*/ 0x00,0x00,0xfc,0x66,0x66,0x66,0x7c,0x60,0x60,0x60,0x60,0xf0,0x00,0x00,0x00,0x00,
|
||||
/*Q*/ 0x00,0x00,0x7c,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0xd6,0xde,0x7c,0x0c,0x0e,0x00,0x00,
|
||||
/*R*/ 0x00,0x00,0xfc,0x66,0x66,0x66,0x7c,0x6c,0x66,0x66,0x66,0xe6,0x00,0x00,0x00,0x00,
|
||||
/*S*/ 0x00,0x00,0x7c,0xc6,0xc6,0x60,0x38,0x0c,0x06,0xc6,0xc6,0x7c,0x00,0x00,0x00,0x00,
|
||||
/*T*/ 0x00,0x00,0xff,0xdb,0x99,0x18,0x18,0x18,0x18,0x18,0x18,0x3c,0x00,0x00,0x00,0x00,
|
||||
/*U*/ 0x00,0x00,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0x7c,0x00,0x00,0x00,0x00,
|
||||
/*V*/ 0x00,0x00,0xc3,0xc3,0xc3,0xc3,0xc3,0xc3,0xc3,0x66,0x3c,0x18,0x00,0x00,0x00,0x00,
|
||||
/*W*/ 0x00,0x00,0xc3,0xc3,0xc3,0xc3,0xc3,0xdb,0xdb,0xff,0x66,0x66,0x00,0x00,0x00,0x00,
|
||||
/*X*/ 0x00,0x00,0xc3,0xc3,0x66,0x3c,0x18,0x18,0x3c,0x66,0xc3,0xc3,0x00,0x00,0x00,0x00,
|
||||
/*Y*/ 0x00,0x00,0xc3,0xc3,0xc3,0x66,0x3c,0x18,0x18,0x18,0x18,0x3c,0x00,0x00,0x00,0x00,
|
||||
/*Z*/ 0x00,0x00,0xff,0xc3,0x86,0x0c,0x18,0x30,0x60,0xc1,0xc3,0xff,0x00,0x00,0x00,0x00,
|
||||
/*[*/ 0x00,0x00,0x3c,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x3c,0x00,0x00,0x00,0x00,
|
||||
/*\*/ 0x00,0x00,0x00,0x80,0xc0,0xe0,0x70,0x38,0x1c,0x0e,0x06,0x02,0x00,0x00,0x00,0x00,
|
||||
/*]*/ 0x00,0x00,0x3c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x3c,0x00,0x00,0x00,0x00,
|
||||
/*^*/ 0x10,0x38,0x6c,0xc6,0x00,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,0x00,0x00,
|
||||
/* */ 0x30,0x30,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
/*a*/ 0x00,0x00,0x00,0x00,0x00,0x78,0x0c,0x7c,0xcc,0xcc,0xcc,0x76,0x00,0x00,0x00,0x00,
|
||||
/*b*/ 0x00,0x00,0xe0,0x60,0x60,0x78,0x6c,0x66,0x66,0x66,0x66,0x7c,0x00,0x00,0x00,0x00,
|
||||
/*c*/ 0x00,0x00,0x00,0x00,0x00,0x7c,0xc6,0xc0,0xc0,0xc0,0xc6,0x7c,0x00,0x00,0x00,0x00,
|
||||
/*d*/ 0x00,0x00,0x1c,0x0c,0x0c,0x3c,0x6c,0xcc,0xcc,0xcc,0xcc,0x76,0x00,0x00,0x00,0x00,
|
||||
/*e*/ 0x00,0x00,0x00,0x00,0x00,0x7c,0xc6,0xfe,0xc0,0xc0,0xc6,0x7c,0x00,0x00,0x00,0x00,
|
||||
/*f*/ 0x00,0x00,0x38,0x6c,0x64,0x60,0xf0,0x60,0x60,0x60,0x60,0xf0,0x00,0x00,0x00,0x00,
|
||||
/*g*/ 0x00,0x00,0x00,0x00,0x00,0x76,0xcc,0xcc,0xcc,0xcc,0xcc,0x7c,0x0c,0xcc,0x78,0x00,
|
||||
/*h*/ 0x00,0x00,0xe0,0x60,0x60,0x6c,0x76,0x66,0x66,0x66,0x66,0xe6,0x00,0x00,0x00,0x00,
|
||||
/*i*/ 0x00,0x00,0x18,0x18,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x3c,0x00,0x00,0x00,0x00,
|
||||
/*j*/ 0x00,0x00,0x06,0x06,0x00,0x0e,0x06,0x06,0x06,0x06,0x06,0x06,0x66,0x66,0x3c,0x00,
|
||||
/*k*/ 0x00,0x00,0xe0,0x60,0x60,0x66,0x6c,0x78,0x78,0x6c,0x66,0xe6,0x00,0x00,0x00,0x00,
|
||||
/*l*/ 0x00,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x3c,0x00,0x00,0x00,0x00,
|
||||
/*m*/ 0x00,0x00,0x00,0x00,0x00,0xe6,0xff,0xdb,0xdb,0xdb,0xdb,0xdb,0x00,0x00,0x00,0x00,
|
||||
/*n*/ 0x00,0x00,0x00,0x00,0x00,0xdc,0x66,0x66,0x66,0x66,0x66,0x66,0x00,0x00,0x00,0x00,
|
||||
/*o*/ 0x00,0x00,0x00,0x00,0x00,0x7c,0xc6,0xc6,0xc6,0xc6,0xc6,0x7c,0x00,0x00,0x00,0x00,
|
||||
/*p*/ 0x00,0x00,0x00,0x00,0x00,0xdc,0x66,0x66,0x66,0x66,0x66,0x7c,0x60,0x60,0xf0,0x00,
|
||||
/*q*/ 0x00,0x00,0x00,0x00,0x00,0x76,0xcc,0xcc,0xcc,0xcc,0xcc,0x7c,0x0c,0x0c,0x1e,0x00,
|
||||
/*r*/ 0x00,0x00,0x00,0x00,0x00,0xdc,0x76,0x66,0x60,0x60,0x60,0xf0,0x00,0x00,0x00,0x00,
|
||||
/*s*/ 0x00,0x00,0x00,0x00,0x00,0x7c,0xc6,0x60,0x38,0x0c,0xc6,0x7c,0x00,0x00,0x00,0x00,
|
||||
/*t*/ 0x00,0x00,0x10,0x30,0x30,0xfc,0x30,0x30,0x30,0x30,0x36,0x1c,0x00,0x00,0x00,0x00,
|
||||
/*u*/ 0x00,0x00,0x00,0x00,0x00,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0x76,0x00,0x00,0x00,0x00,
|
||||
/*v*/ 0x00,0x00,0x00,0x00,0x00,0xc3,0xc3,0xc3,0xc3,0x66,0x3c,0x18,0x00,0x00,0x00,0x00,
|
||||
/*w*/ 0x00,0x00,0x00,0x00,0x00,0xc3,0xc3,0xc3,0xdb,0xdb,0xff,0x66,0x00,0x00,0x00,0x00,
|
||||
/*x*/ 0x00,0x00,0x00,0x00,0x00,0xc3,0x66,0x3c,0x18,0x3c,0x66,0xc3,0x00,0x00,0x00,0x00,
|
||||
/*y*/ 0x00,0x00,0x00,0x00,0x00,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0x7e,0x06,0x0c,0xf8,0x00,
|
||||
/*z*/ 0x00,0x00,0x00,0x00,0x00,0xfe,0xcc,0x18,0x30,0x60,0xc6,0xfe,0x00,0x00,0x00,0x00,
|
||||
/*{*/ 0x00,0x00,0x0e,0x18,0x18,0x18,0x70,0x18,0x18,0x18,0x18,0x0e,0x00,0x00,0x00,0x00,
|
||||
/*|*/ 0x00,0x00,0x18,0x18,0x18,0x18,0x00,0x18,0x18,0x18,0x18,0x18,0x00,0x00,0x00,0x00,
|
||||
/*}*/ 0x00,0x00,0x70,0x18,0x18,0x18,0x0e,0x18,0x18,0x18,0x18,0x70,0x00,0x00,0x00,0x00,
|
||||
/*~*/ 0x00,0x00,0x76,0xdc,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
/* */ 0x00,0x00,0x00,0x00,0x10,0x38,0x6c,0xc6,0xc6,0xc6,0xfe,0x00,0x00,0x00,0x00,0x00,
|
||||
/* */ 0x00,0x00,0x3c,0x66,0xc2,0xc0,0xc0,0xc0,0xc2,0x66,0x3c,0x0c,0x06,0x7c,0x00,0x00,
|
||||
/* */ 0x00,0x00,0xcc,0x00,0x00,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0x76,0x00,0x00,0x00,0x00,
|
||||
/* */ 0x00,0x0c,0x18,0x30,0x00,0x7c,0xc6,0xfe,0xc0,0xc0,0xc6,0x7c,0x00,0x00,0x00,0x00,
|
||||
/* */ 0x00,0x10,0x38,0x6c,0x00,0x78,0x0c,0x7c,0xcc,0xcc,0xcc,0x76,0x00,0x00,0x00,0x00,
|
||||
/* */ 0x00,0x00,0xcc,0x00,0x00,0x78,0x0c,0x7c,0xcc,0xcc,0xcc,0x76,0x00,0x00,0x00,0x00,
|
||||
/* */ 0x00,0x60,0x30,0x18,0x00,0x78,0x0c,0x7c,0xcc,0xcc,0xcc,0x76,0x00,0x00,0x00,0x00,
|
||||
/* */ 0x00,0x38,0x6c,0x38,0x00,0x78,0x0c,0x7c,0xcc,0xcc,0xcc,0x76,0x00,0x00,0x00,0x00,
|
||||
/* */ 0x00,0x00,0x00,0x00,0x3c,0x66,0x60,0x60,0x66,0x3c,0x0c,0x06,0x3c,0x00,0x00,0x00,
|
||||
/* */ 0x00,0x10,0x38,0x6c,0x00,0x7c,0xc6,0xfe,0xc0,0xc0,0xc6,0x7c,0x00,0x00,0x00,0x00,
|
||||
/* */ 0x00,0x00,0xc6,0x00,0x00,0x7c,0xc6,0xfe,0xc0,0xc0,0xc6,0x7c,0x00,0x00,0x00,0x00,
|
||||
/* */ 0x00,0x60,0x30,0x18,0x00,0x7c,0xc6,0xfe,0xc0,0xc0,0xc6,0x7c,0x00,0x00,0x00,0x00,
|
||||
/* */ 0x00,0x00,0x66,0x00,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x3c,0x00,0x00,0x00,0x00,
|
||||
/* */ 0x00,0x18,0x3c,0x66,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x3c,0x00,0x00,0x00,0x00,
|
||||
/* */ 0x00,0x60,0x30,0x18,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x3c,0x00,0x00,0x00,0x00,
|
||||
/* */ 0x00,0xc6,0x00,0x10,0x38,0x6c,0xc6,0xc6,0xfe,0xc6,0xc6,0xc6,0x00,0x00,0x00,0x00,
|
||||
/* */ 0x38,0x6c,0x38,0x00,0x38,0x6c,0xc6,0xc6,0xfe,0xc6,0xc6,0xc6,0x00,0x00,0x00,0x00,
|
||||
/* */ 0x18,0x30,0x60,0x00,0xfe,0x66,0x60,0x7c,0x60,0x60,0x66,0xfe,0x00,0x00,0x00,0x00,
|
||||
/* */ 0x00,0x00,0x00,0x00,0x00,0x6e,0x3b,0x1b,0x7e,0xd8,0xdc,0x77,0x00,0x00,0x00,0x00,
|
||||
/* */ 0x00,0x00,0x3e,0x6c,0xcc,0xcc,0xfe,0xcc,0xcc,0xcc,0xcc,0xce,0x00,0x00,0x00,0x00,
|
||||
/* */ 0x00,0x10,0x38,0x6c,0x00,0x7c,0xc6,0xc6,0xc6,0xc6,0xc6,0x7c,0x00,0x00,0x00,0x00,
|
||||
/* */ 0x00,0x00,0xc6,0x00,0x00,0x7c,0xc6,0xc6,0xc6,0xc6,0xc6,0x7c,0x00,0x00,0x00,0x00,
|
||||
/* */ 0x00,0x60,0x30,0x18,0x00,0x7c,0xc6,0xc6,0xc6,0xc6,0xc6,0x7c,0x00,0x00,0x00,0x00,
|
||||
/* */ 0x00,0x30,0x78,0xcc,0x00,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0x76,0x00,0x00,0x00,0x00,
|
||||
/* */ 0x00,0x60,0x30,0x18,0x00,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0x76,0x00,0x00,0x00,0x00,
|
||||
/* */ 0x00,0x00,0xc6,0x00,0x00,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0x7e,0x06,0x0c,0x78,0x00,
|
||||
/* */ 0x00,0xc6,0x00,0x7c,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0x7c,0x00,0x00,0x00,0x00,
|
||||
/* */ 0x00,0xc6,0x00,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0x7c,0x00,0x00,0x00,0x00,
|
||||
/* */ 0x00,0x18,0x18,0x7e,0xc3,0xc0,0xc0,0xc0,0xc3,0x7e,0x18,0x18,0x00,0x00,0x00,0x00,
|
||||
/* */ 0x00,0x38,0x6c,0x64,0x60,0xf0,0x60,0x60,0x60,0x60,0xe6,0xfc,0x00,0x00,0x00,0x00,
|
||||
/* */ 0x00,0x00,0xc3,0x66,0x3c,0x18,0xff,0x18,0xff,0x18,0x18,0x18,0x00,0x00,0x00,0x00,
|
||||
/* */ 0x00,0xfc,0x66,0x66,0x7c,0x62,0x66,0x6f,0x66,0x66,0x66,0xf3,0x00,0x00,0x00,0x00,
|
||||
/* */ 0x00,0x0e,0x1b,0x18,0x18,0x18,0x7e,0x18,0x18,0x18,0x18,0x18,0xd8,0x70,0x00,0x00,
|
||||
/* */ 0x00,0x18,0x30,0x60,0x00,0x78,0x0c,0x7c,0xcc,0xcc,0xcc,0x76,0x00,0x00,0x00,0x00,
|
||||
/* */ 0x00,0x0c,0x18,0x30,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x3c,0x00,0x00,0x00,0x00,
|
||||
/* */ 0x00,0x18,0x30,0x60,0x00,0x7c,0xc6,0xc6,0xc6,0xc6,0xc6,0x7c,0x00,0x00,0x00,0x00,
|
||||
/* */ 0x00,0x18,0x30,0x60,0x00,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0x76,0x00,0x00,0x00,0x00,
|
||||
/* */ 0x00,0x00,0x76,0xdc,0x00,0xdc,0x66,0x66,0x66,0x66,0x66,0x66,0x00,0x00,0x00,0x00,
|
||||
/* */ 0x76,0xdc,0x00,0xc6,0xe6,0xf6,0xfe,0xde,0xce,0xc6,0xc6,0xc6,0x00,0x00,0x00,0x00,
|
||||
/* */ 0x00,0x3c,0x6c,0x6c,0x3e,0x00,0x7e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
/* */ 0x00,0x38,0x6c,0x6c,0x38,0x00,0x7c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
/* */ 0x00,0x00,0x30,0x30,0x00,0x30,0x30,0x60,0xc0,0xc6,0xc6,0x7c,0x00,0x00,0x00,0x00,
|
||||
/* */ 0x00,0x00,0x00,0x00,0x00,0x00,0xfe,0xc0,0xc0,0xc0,0xc0,0x00,0x00,0x00,0x00,0x00,
|
||||
/* */ 0x00,0x00,0x00,0x00,0x00,0x00,0xfe,0x06,0x06,0x06,0x06,0x00,0x00,0x00,0x00,0x00,
|
||||
/* */ 0x00,0xc0,0xc0,0xc2,0xc6,0xcc,0x18,0x30,0x60,0xce,0x9b,0x06,0x0c,0x1f,0x00,0x00,
|
||||
/* */ 0x00,0xc0,0xc0,0xc2,0xc6,0xcc,0x18,0x30,0x66,0xce,0x96,0x3e,0x06,0x06,0x00,0x00,
|
||||
/* */ 0x00,0x00,0x18,0x18,0x00,0x18,0x18,0x18,0x3c,0x3c,0x3c,0x18,0x00,0x00,0x00,0x00,
|
||||
/* */ 0x00,0x00,0x00,0x00,0x00,0x36,0x6c,0xd8,0x6c,0x36,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
/* */ 0x00,0x00,0x00,0x00,0x00,0xd8,0x6c,0x36,0x6c,0xd8,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
/* */ 0x11,0x44,0x11,0x44,0x11,0x44,0x11,0x44,0x11,0x44,0x11,0x44,0x11,0x44,0x11,0x44,
|
||||
/* */ 0x55,0xaa,0x55,0xaa,0x55,0xaa,0x55,0xaa,0x55,0xaa,0x55,0xaa,0x55,0xaa,0x55,0xaa,
|
||||
/* */ 0xdd,0x77,0xdd,0x77,0xdd,0x77,0xdd,0x77,0xdd,0x77,0xdd,0x77,0xdd,0x77,0xdd,0x77,
|
||||
/* */ 0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,
|
||||
/* */ 0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xf8,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,
|
||||
/* */ 0x18,0x18,0x18,0x18,0x18,0xf8,0x18,0xf8,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,
|
||||
/* */ 0x36,0x36,0x36,0x36,0x36,0x36,0x36,0xf6,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,
|
||||
/* */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfe,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,
|
||||
/* */ 0x00,0x00,0x00,0x00,0x00,0xf8,0x18,0xf8,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,
|
||||
/* */ 0x36,0x36,0x36,0x36,0x36,0xf6,0x06,0xf6,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,
|
||||
/* */ 0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,
|
||||
/* */ 0x00,0x00,0x00,0x00,0x00,0xfe,0x06,0xf6,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,
|
||||
/* */ 0x36,0x36,0x36,0x36,0x36,0xf6,0x06,0xfe,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
/* */ 0x36,0x36,0x36,0x36,0x36,0x36,0x36,0xfe,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
/* */ 0x18,0x18,0x18,0x18,0x18,0xf8,0x18,0xf8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
/* */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf8,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,
|
||||
/* */ 0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x1f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
/* */ 0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
/* */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,
|
||||
/* */ 0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x1f,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,
|
||||
/* */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
/* */ 0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xff,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,
|
||||
/* */ 0x18,0x18,0x18,0x18,0x18,0x1f,0x18,0x1f,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,
|
||||
/* */ 0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x37,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,
|
||||
/* */ 0x36,0x36,0x36,0x36,0x36,0x37,0x30,0x3f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
/* */ 0x00,0x00,0x00,0x00,0x00,0x3f,0x30,0x37,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,
|
||||
/* */ 0x36,0x36,0x36,0x36,0x36,0xf7,0x00,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
/* */ 0x00,0x00,0x00,0x00,0x00,0xff,0x00,0xf7,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,
|
||||
/* */ 0x36,0x36,0x36,0x36,0x36,0x37,0x30,0x37,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,
|
||||
/* */ 0x00,0x00,0x00,0x00,0x00,0xff,0x00,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
/* */ 0x36,0x36,0x36,0x36,0x36,0xf7,0x00,0xf7,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,
|
||||
/* */ 0x18,0x18,0x18,0x18,0x18,0xff,0x00,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
/* */ 0x36,0x36,0x36,0x36,0x36,0x36,0x36,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
/* */ 0x00,0x00,0x00,0x00,0x00,0xff,0x00,0xff,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,
|
||||
/* */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,
|
||||
/* */ 0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x3f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
/* */ 0x18,0x18,0x18,0x18,0x18,0x1f,0x18,0x1f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
/* */ 0x00,0x00,0x00,0x00,0x00,0x1f,0x18,0x1f,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,
|
||||
/* */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3f,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,
|
||||
/* */ 0x36,0x36,0x36,0x36,0x36,0x36,0x36,0xff,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,
|
||||
/* */ 0x18,0x18,0x18,0x18,0x18,0xff,0x18,0xff,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,
|
||||
/* */ 0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xf8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
/* */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1f,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,
|
||||
/* */ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
|
||||
/* */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
|
||||
/* */ 0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,
|
||||
/* */ 0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,
|
||||
/* */ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
/* */ 0x00,0x00,0x00,0x00,0x00,0x76,0xdc,0xd8,0xd8,0xd8,0xdc,0x76,0x00,0x00,0x00,0x00,
|
||||
/* */ 0x00,0x00,0x78,0xcc,0xcc,0xcc,0xd8,0xcc,0xc6,0xc6,0xc6,0xcc,0x00,0x00,0x00,0x00,
|
||||
/* */ 0x00,0x00,0xfe,0xc6,0xc6,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0x00,0x00,0x00,0x00,
|
||||
/* */ 0x00,0x00,0x00,0x00,0xfe,0x6c,0x6c,0x6c,0x6c,0x6c,0x6c,0x6c,0x00,0x00,0x00,0x00,
|
||||
/* */ 0x00,0x00,0x00,0xfe,0xc6,0x60,0x30,0x18,0x30,0x60,0xc6,0xfe,0x00,0x00,0x00,0x00,
|
||||
/* */ 0x00,0x00,0x00,0x00,0x00,0x7e,0xd8,0xd8,0xd8,0xd8,0xd8,0x70,0x00,0x00,0x00,0x00,
|
||||
/* */ 0x00,0x00,0x00,0x00,0x66,0x66,0x66,0x66,0x66,0x7c,0x60,0x60,0xc0,0x00,0x00,0x00,
|
||||
/* */ 0x00,0x00,0x00,0x00,0x76,0xdc,0x18,0x18,0x18,0x18,0x18,0x18,0x00,0x00,0x00,0x00,
|
||||
/* */ 0x00,0x00,0x00,0x7e,0x18,0x3c,0x66,0x66,0x66,0x3c,0x18,0x7e,0x00,0x00,0x00,0x00,
|
||||
/* */ 0x00,0x00,0x00,0x38,0x6c,0xc6,0xc6,0xfe,0xc6,0xc6,0x6c,0x38,0x00,0x00,0x00,0x00,
|
||||
/* */ 0x00,0x00,0x38,0x6c,0xc6,0xc6,0xc6,0x6c,0x6c,0x6c,0x6c,0xee,0x00,0x00,0x00,0x00,
|
||||
/* */ 0x00,0x00,0x1e,0x30,0x18,0x0c,0x3e,0x66,0x66,0x66,0x66,0x3c,0x00,0x00,0x00,0x00,
|
||||
/* */ 0x00,0x00,0x00,0x00,0x00,0x7e,0xdb,0xdb,0xdb,0x7e,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
/* */ 0x00,0x00,0x00,0x03,0x06,0x7e,0xdb,0xdb,0xf3,0x7e,0x60,0xc0,0x00,0x00,0x00,0x00,
|
||||
/* */ 0x00,0x00,0x1c,0x30,0x60,0x60,0x7c,0x60,0x60,0x60,0x30,0x1c,0x00,0x00,0x00,0x00,
|
||||
/* */ 0x00,0x00,0x00,0x7c,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0x00,0x00,0x00,0x00,
|
||||
/* */ 0x00,0x00,0x00,0x00,0xfe,0x00,0x00,0xfe,0x00,0x00,0xfe,0x00,0x00,0x00,0x00,0x00,
|
||||
/* */ 0x00,0x00,0x00,0x00,0x18,0x18,0x7e,0x18,0x18,0x00,0x00,0xff,0x00,0x00,0x00,0x00,
|
||||
/* */ 0x00,0x00,0x00,0x30,0x18,0x0c,0x06,0x0c,0x18,0x30,0x00,0x7e,0x00,0x00,0x00,0x00,
|
||||
/* */ 0x00,0x00,0x00,0x0c,0x18,0x30,0x60,0x30,0x18,0x0c,0x00,0x7e,0x00,0x00,0x00,0x00,
|
||||
/* */ 0x00,0x00,0x0e,0x1b,0x1b,0x1b,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,
|
||||
/* */ 0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xd8,0xd8,0xd8,0x70,0x00,0x00,0x00,0x00,
|
||||
/* */ 0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x7e,0x00,0x18,0x18,0x00,0x00,0x00,0x00,0x00,
|
||||
/* */ 0x00,0x00,0x00,0x00,0x00,0x76,0xdc,0x00,0x76,0xdc,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
/* */ 0x00,0x38,0x6c,0x6c,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
/* */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
/* */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
/* */ 0x00,0x0f,0x0c,0x0c,0x0c,0x0c,0x0c,0xec,0x6c,0x6c,0x3c,0x1c,0x00,0x00,0x00,0x00,
|
||||
/* */ 0x00,0xd8,0x6c,0x6c,0x6c,0x6c,0x6c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
/* */ 0x00,0x70,0xd8,0x30,0x60,0xc8,0xf8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
/* */ 0x00,0x00,0x00,0x00,0x7c,0x7c,0x7c,0x7c,0x7c,0x7c,0x7c,0x00,0x00,0x00,0x00,0x00,
|
||||
/* */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
};
|
||||
|
||||
#undef FONTDATAMAX
|
||||
|
19
src/device/graphics/Fonts.cc
Normal file
19
src/device/graphics/Fonts.cc
Normal file
@ -0,0 +1,19 @@
|
||||
// Jakob Falke, oostubs
|
||||
// Github: https://gitlab.cs.fau.de/um15ebek/oostubs
|
||||
|
||||
// vim: set et ts=4 sw=4:
|
||||
|
||||
#include "Fonts.h"
|
||||
#include "Font_8x16.h"
|
||||
#include "Font_8x8.h"
|
||||
#include "Font_acorn_8x8.h"
|
||||
#include "Font_pearl_8x8.h"
|
||||
#include "Font_sun_12x22.h"
|
||||
#include "Font_sun_8x16.h"
|
||||
|
||||
const Font_8x16 std_font_8x16;
|
||||
const Font_8x8 std_font_8x8;
|
||||
const Font_acorn_8x8 acorn_font_8x8;
|
||||
const Font_pearl_8x8 pearl_font_8x8;
|
||||
const Font_sun_12x22 sun_font_12x22;
|
||||
const Font_sun_8x16 sun_font_8x16;
|
67
src/device/graphics/Fonts.h
Normal file
67
src/device/graphics/Fonts.h
Normal file
@ -0,0 +1,67 @@
|
||||
// Jakob Falke, oostubs
|
||||
// Github: https://gitlab.cs.fau.de/um15ebek/oostubs
|
||||
|
||||
// Schriften in Form von Rastergrafiken (separate Datein)
|
||||
// Generiert mit cpi2fnt
|
||||
// Keine Proportionalschriften
|
||||
// Monochrome Speicherung: 1 Bit pro Pixel
|
||||
// Je nach Breite wird auf Bytegrenzen aufgerundet:
|
||||
// 8 Pixel -> 1 Byte; 12 Pixel -> 2 Byte
|
||||
|
||||
#ifndef FONTS_H__
|
||||
#define FONTS_H__
|
||||
|
||||
#include "lib/util/Array.h"
|
||||
|
||||
class Font {
|
||||
public:
|
||||
virtual ~Font() = default;
|
||||
|
||||
virtual const unsigned char* getChar(int c) const = 0;
|
||||
virtual unsigned int get_char_width() const = 0;
|
||||
virtual unsigned int get_char_height() const = 0;
|
||||
};
|
||||
|
||||
template<unsigned int width, unsigned int height, const unsigned char* data>
|
||||
class FontInstance : public Font {
|
||||
const unsigned int char_width;
|
||||
const unsigned int char_height;
|
||||
const unsigned int char_mem_size;
|
||||
const unsigned char* font_data;
|
||||
|
||||
public:
|
||||
FontInstance() : char_width(width), char_height(height), char_mem_size((((char_width + (8 >> 1)) / 8) * char_height)), font_data(data) {}
|
||||
|
||||
inline const unsigned char* getChar(int c) const override {
|
||||
return &font_data[char_mem_size * c];
|
||||
}
|
||||
inline unsigned int get_char_width() const override {
|
||||
return char_width;
|
||||
}
|
||||
inline unsigned int get_char_height() const override {
|
||||
return char_height;
|
||||
}
|
||||
};
|
||||
|
||||
extern const unsigned char fontdata_8x16[];
|
||||
extern const unsigned char fontdata_8x8[];
|
||||
extern const unsigned char acorndata_8x8[];
|
||||
extern const unsigned char fontdata_pearl_8x8[];
|
||||
extern const unsigned char fontdata_sun_12x22[];
|
||||
extern const unsigned char fontdata_sun_8x16[];
|
||||
|
||||
using Font_8x16 = FontInstance<8, 16, fontdata_8x16>;
|
||||
using Font_8x8 = FontInstance<8, 8, fontdata_8x8>;
|
||||
using Font_acorn_8x8 = FontInstance<8, 8, acorndata_8x8>;
|
||||
using Font_pearl_8x8 = FontInstance<8, 8, fontdata_pearl_8x8>;
|
||||
using Font_sun_12x22 = FontInstance<12, 22, fontdata_sun_12x22>;
|
||||
using Font_sun_8x16 = FontInstance<8, 16, fontdata_sun_8x16>;
|
||||
|
||||
extern const Font_8x16 std_font_8x16;
|
||||
extern const Font_8x8 std_font_8x8;
|
||||
extern const Font_acorn_8x8 acorn_font_8x8;
|
||||
extern const Font_pearl_8x8 pearl_font_8x8;
|
||||
extern const Font_sun_12x22 sun_font_12x22;
|
||||
extern const Font_sun_8x16 sun_font_8x16;
|
||||
|
||||
#endif
|
291
src/device/graphics/LFBgraphics.cc
Normal file
291
src/device/graphics/LFBgraphics.cc
Normal file
@ -0,0 +1,291 @@
|
||||
/*****************************************************************************
|
||||
* *
|
||||
* L F B G R A P H I C S *
|
||||
* *
|
||||
*---------------------------------------------------------------------------*
|
||||
* Beschreibung: Zeichenfunktionen fuer Grafikmodi, die auf einem *
|
||||
* linearen Framebuffer basieren. Verwendet in VESA und *
|
||||
* QemuVGA. *
|
||||
* *
|
||||
* Autor: Michael Schoettner, HHU, 19.9.2016 *
|
||||
* Der Code fuer das Zeichnen der Linie ist von Alan Wolfe *
|
||||
* https://blog.demofox.org/2015/01/17/bresenhams-drawing-algorithms *
|
||||
*****************************************************************************/
|
||||
|
||||
#include "LFBgraphics.h"
|
||||
|
||||
/* Hilfsfunktionen */
|
||||
void swap(unsigned int* a, unsigned int* b);
|
||||
int abs(int a);
|
||||
|
||||
/*****************************************************************************
|
||||
* Methode: LFBgraphics::drawMonoBitmap *
|
||||
*---------------------------------------------------------------------------*
|
||||
* Parameter: x,y Startpunkt ab dem Text ausgegeben wird. *
|
||||
* width Breite in Pixel *
|
||||
* height Hoehe in Pixel *
|
||||
* bitmap Zeiger auf Pixel der monochromen Rastergrafik *
|
||||
* col Farbe der Pixel *
|
||||
* *
|
||||
* Beschreibung: Gibt die gegebene monochrome Rastergrafik an der Position*
|
||||
* x,y zeilenweise aus. (x,y) ist der linke obere Punkt; *
|
||||
* ist in der bitmap eine '1', so wird ein Pixel mit der *
|
||||
* Farbe col ausgegeben, ansonsten bei '0' nichts. *
|
||||
* Diese Funktion basiert auf dem Format der Fonts, welche *
|
||||
* mit cpi2fnt (AmigaOS) erzeugt wurden. Das Format erklaert*
|
||||
* sich in den C-Dateien in fonts/ von selbst. *
|
||||
*****************************************************************************/
|
||||
inline void LFBgraphics::drawMonoBitmap(unsigned int x, unsigned int y,
|
||||
unsigned int width, unsigned int height,
|
||||
const unsigned char* bitmap, unsigned int color) const {
|
||||
// Breite in Bytes
|
||||
unsigned short width_byte = width / 8 + ((width % 8 != 0) ? 1 : 0);
|
||||
|
||||
for (unsigned int yoff = 0; yoff < height; ++yoff) {
|
||||
unsigned int xpos = x;
|
||||
unsigned int ypos = y + yoff;
|
||||
for (unsigned int xb = 0; xb < width_byte; ++xb) {
|
||||
for (int src = 7; src >= 0; --src) {
|
||||
if ((1 << src) & *bitmap) {
|
||||
drawPixel(xpos, ypos, color);
|
||||
}
|
||||
xpos++;
|
||||
}
|
||||
bitmap++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* Methode: LFBgraphics::drawString *
|
||||
*---------------------------------------------------------------------------*
|
||||
* Parameter: fnt Schrift *
|
||||
* x,y Startpunkt ab dem Text ausgegeben wird. *
|
||||
* col Farbe des Textes *
|
||||
* str Zeiger auf Zeichenkette *
|
||||
* len Laenge der Zeichenkette *
|
||||
* *
|
||||
* Beschreibung: Gibt eine Zeichenkette mit gewaehlter Schrift an der *
|
||||
* Position x,y aus. *
|
||||
*****************************************************************************/
|
||||
void LFBgraphics::drawString(const Font& fnt, unsigned int x, unsigned int y,
|
||||
unsigned int col, const char* str, unsigned int len) const {
|
||||
for (unsigned int i = 0; i < len; ++i) {
|
||||
drawMonoBitmap(x, y, fnt.get_char_width(), fnt.get_char_height(), fnt.getChar(*(str + i)), col);
|
||||
x += fnt.get_char_width();
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* Methode: LFBgraphics::drawPixel *
|
||||
*---------------------------------------------------------------------------*
|
||||
* Parameter: x, y Koordinaten des Pixels *
|
||||
* col Farbe *
|
||||
* *
|
||||
* Beschreibung: Zeichnen eines Pixels. *
|
||||
*****************************************************************************/
|
||||
void LFBgraphics::drawPixel(unsigned int x, unsigned int y, unsigned int col) const {
|
||||
unsigned char* ptr = reinterpret_cast<unsigned char*>(lfb);
|
||||
|
||||
if (hfb == 0 || lfb == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (mode == BUFFER_INVISIBLE) {
|
||||
ptr = reinterpret_cast<unsigned char*>(hfb);
|
||||
}
|
||||
|
||||
// Pixel ausserhalb des sichtbaren Bereichs?
|
||||
if (x < 0 || x >= xres || y < 0 || y > yres) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Adresse des Pixels berechnen und Inhalt schreiben
|
||||
switch (bpp) {
|
||||
case 8:
|
||||
ptr += (x + y * xres);
|
||||
*ptr = col;
|
||||
return;
|
||||
case 15:
|
||||
case 16:
|
||||
ptr += (2 * x + 2 * y * xres);
|
||||
*ptr = col;
|
||||
return;
|
||||
case 24:
|
||||
ptr += (3 * x + 3 * y * xres);
|
||||
*ptr = (col & 0xFF);
|
||||
ptr++;
|
||||
*ptr = ((col >> 8) & 0xFF);
|
||||
ptr++;
|
||||
*ptr = ((col >> 16) & 0xFF);
|
||||
ptr;
|
||||
return;
|
||||
case 32:
|
||||
ptr += (4 * x + 4 * y * xres);
|
||||
*ptr = (col & 0xFF);
|
||||
ptr++;
|
||||
*ptr = ((col >> 8) & 0xFF);
|
||||
ptr++;
|
||||
*ptr = ((col >> 16) & 0xFF);
|
||||
ptr;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void LFBgraphics::drawStraightLine(unsigned int x1, unsigned int y1, unsigned int x2, unsigned int y2, unsigned int col) const {
|
||||
// Don't set mode inside the drawing function to use them in animations
|
||||
|
||||
if (x1 == x2 && y2 > y1) {
|
||||
// Vertical line
|
||||
for (unsigned int i = y1; i <= y2; ++i) {
|
||||
drawPixel(x1, i, col);
|
||||
}
|
||||
} else if (y1 == y2 && x2 > x1) {
|
||||
// Horizontal line
|
||||
for (unsigned int i = x1; i <= x2; ++i) {
|
||||
drawPixel(i, y1, col);
|
||||
}
|
||||
} else {
|
||||
// Not straight
|
||||
}
|
||||
}
|
||||
|
||||
// (x1, y1)---(x2, y1)
|
||||
// | |
|
||||
// (x1, y2)---(x2, y2)
|
||||
void LFBgraphics::drawRectangle(unsigned int x1, unsigned int y1, unsigned int x2, unsigned int y2, unsigned int col) const {
|
||||
drawStraightLine(x1, y1, x2, y1, col);
|
||||
drawStraightLine(x2, y1, x2, y2, col);
|
||||
drawStraightLine(x1, y2, x2, y2, col);
|
||||
drawStraightLine(x1, y1, x1, y2, col);
|
||||
}
|
||||
|
||||
void LFBgraphics::drawCircle(unsigned int x, unsigned int y, unsigned int rad, unsigned int col) const {
|
||||
// TODO
|
||||
}
|
||||
|
||||
void LFBgraphics::drawSprite(unsigned int width, unsigned int height, unsigned int bytes_pp, const unsigned char* pixel_data) const {
|
||||
const unsigned char* ptr;
|
||||
for (unsigned int x = 0; x < width; ++x) {
|
||||
for (unsigned int y = 0; y < height; ++y) {
|
||||
ptr = pixel_data + (x + y * width) * bytes_pp;
|
||||
|
||||
switch (bytes_pp) {
|
||||
case 2:
|
||||
// TODO: Never tested, probably doesn't work
|
||||
drawPixel(x, y, RGB_24(*ptr & 0b11111000, ((*ptr & 0b111) << 3) | (*(ptr + 1) >> 5),
|
||||
*(ptr + 1) & 0b11111)); // RGB 565
|
||||
break;
|
||||
case 3:
|
||||
case 4:
|
||||
// Alpha gets ignored anyway
|
||||
drawPixel(x, y, RGB_24(*ptr, *(ptr + 1), *(ptr + 2)));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* Methode: LFBgraphics::clear *
|
||||
*---------------------------------------------------------------------------*
|
||||
* Beschreibung: Bildschirm loeschen. *
|
||||
*****************************************************************************/
|
||||
void LFBgraphics::clear() const {
|
||||
unsigned int* ptr = reinterpret_cast<unsigned int*>(lfb);
|
||||
unsigned int i;
|
||||
|
||||
if (hfb == 0 || lfb == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (mode == 0) {
|
||||
ptr = reinterpret_cast<unsigned int*>(hfb);
|
||||
}
|
||||
|
||||
switch (bpp) {
|
||||
case 8:
|
||||
for (i = 0; i < ((xres / 4) * yres); i++) {
|
||||
*(ptr++) = 0;
|
||||
}
|
||||
return;
|
||||
case 15:
|
||||
case 16:
|
||||
for (i = 0; i < (2 * (xres / 4) * yres); i++) {
|
||||
*(ptr++) = 0;
|
||||
}
|
||||
return;
|
||||
case 24:
|
||||
for (i = 0; i < (3 * (xres / 4) * yres); i++) {
|
||||
*(ptr++) = 0;
|
||||
}
|
||||
return;
|
||||
case 32:
|
||||
for (i = 0; i < (4 * (xres / 4) * yres); i++) {
|
||||
*(ptr++) = 0;
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* Methode: LFBgraphics::setDrawingBuff *
|
||||
*---------------------------------------------------------------------------*
|
||||
* Beschreibung: Stellt ein, ob in den sichtbaren Puffer gezeichnet wird. *
|
||||
*****************************************************************************/
|
||||
void LFBgraphics::setDrawingBuff(int v) {
|
||||
mode = v;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* Methode: LFBgraphics::copyHiddenToVisible *
|
||||
*---------------------------------------------------------------------------*
|
||||
* Beschreibung: Kopiert den versteckten Puffer in den sichtbaren LFB. *
|
||||
*****************************************************************************/
|
||||
void LFBgraphics::copyHiddenToVisible() const {
|
||||
unsigned int* sptr = reinterpret_cast<unsigned int*>(hfb);
|
||||
unsigned int* dptr = reinterpret_cast<unsigned int*>(lfb);
|
||||
unsigned int i;
|
||||
|
||||
if (hfb == 0 || lfb == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (bpp) {
|
||||
case 8:
|
||||
for (i = 0; i < ((xres / 4) * yres); i++) {
|
||||
*(dptr++) = *(sptr++);
|
||||
}
|
||||
return;
|
||||
case 15:
|
||||
case 16:
|
||||
for (i = 0; i < (2 * (xres / 4) * yres); i++) {
|
||||
*(dptr++) = *(sptr++);
|
||||
}
|
||||
return;
|
||||
case 24:
|
||||
for (i = 0; i < (3 * (xres / 4) * yres); i++) {
|
||||
*(dptr++) = *(sptr++);
|
||||
}
|
||||
return;
|
||||
case 32:
|
||||
for (i = 0; i < (4 * (xres / 4) * yres); i++) {
|
||||
*(dptr++) = *(sptr++);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void swap(unsigned int* a, unsigned int* b) {
|
||||
unsigned int h = *a;
|
||||
|
||||
*a = *b;
|
||||
*b = h;
|
||||
}
|
||||
|
||||
int abs(int a) {
|
||||
if (a < 0) {
|
||||
return -a;
|
||||
}
|
||||
return a;
|
||||
}
|
64
src/device/graphics/LFBgraphics.h
Normal file
64
src/device/graphics/LFBgraphics.h
Normal file
@ -0,0 +1,64 @@
|
||||
/*****************************************************************************
|
||||
* *
|
||||
* L F B G R A P H I C S *
|
||||
* *
|
||||
*---------------------------------------------------------------------------*
|
||||
* Beschreibung: Zeichenfunktionen fuer Grafikmodi, die auf einem *
|
||||
* linearen Framebuffer basieren. Verwendet in VESA und *
|
||||
* QemuVGA. *
|
||||
* *
|
||||
* Autor: Michael Schoettner, HHU, 19.9.2016 *
|
||||
* Der Code fuer das Zeichnen der Linie ist von Alan Wolfe *
|
||||
* https://blog.demofox.org/2015/01/17/bresenhams-drawing-algorithms *
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef LFBgraphics_include__
|
||||
#define LFBgraphics_include__
|
||||
|
||||
#include "Fonts.h"
|
||||
|
||||
// Hilfsfunktionen um Farbwerte fuer einen Pixel zu erzeugen
|
||||
constexpr unsigned int RGB_24(unsigned int r, unsigned int g, unsigned int b) {
|
||||
return ((r << 16) + (g << 8) + b);
|
||||
}
|
||||
|
||||
constexpr const bool BUFFER_INVISIBLE = false;
|
||||
constexpr const bool BUFFER_VISIBLE = true;
|
||||
|
||||
class LFBgraphics {
|
||||
private:
|
||||
// Hilfsfunktion fuer drawString
|
||||
void drawMonoBitmap(unsigned int x, unsigned int y,
|
||||
unsigned int width, unsigned int height,
|
||||
const unsigned char* bitmap, unsigned int col) const;
|
||||
|
||||
public:
|
||||
LFBgraphics(const LFBgraphics& copy) = delete; // Verhindere Kopieren
|
||||
|
||||
LFBgraphics() : mode(BUFFER_VISIBLE) {};
|
||||
|
||||
unsigned int xres, yres; // Aufloesung in Pixel
|
||||
unsigned int bpp; // Farbtiefe (Bits per Pixel)
|
||||
unsigned int lfb; // Adresse des Linearen Framebuffers
|
||||
unsigned int hfb; // Adresse des versteckten Buffers (optional, fuer Animationen)
|
||||
unsigned int mode; // Zeichnen im sichtbaren = 1 oder unsichtbaren = 0 Puffer
|
||||
|
||||
void clear() const;
|
||||
void drawPixel(unsigned int x, unsigned int y, unsigned int col) const;
|
||||
|
||||
void drawString(const Font& fnt, unsigned int x, unsigned int y, unsigned int col, const char* str, unsigned int len) const;
|
||||
|
||||
void drawCircle(unsigned int x, unsigned int y, unsigned int rad, unsigned int col) const;
|
||||
void drawStraightLine(unsigned int x1, unsigned int y1, unsigned int x2, unsigned int y2, unsigned int col) const;
|
||||
void drawRectangle(unsigned int x1, unsigned int y1, unsigned int x2, unsigned int y2, unsigned int col) const;
|
||||
|
||||
void drawSprite(unsigned int width, unsigned int height, unsigned int bytes_pp, const unsigned char* pixel_data) const;
|
||||
|
||||
// stellt ein, ob in den sichtbaren Puffer gezeichnet wird
|
||||
void setDrawingBuff(int v);
|
||||
|
||||
// kopiert 'hfb' nach 'lfb'
|
||||
void copyHiddenToVisible() const;
|
||||
};
|
||||
|
||||
#endif
|
131
src/device/graphics/VESA.cc
Normal file
131
src/device/graphics/VESA.cc
Normal file
@ -0,0 +1,131 @@
|
||||
/*****************************************************************************
|
||||
* *
|
||||
* V E S A *
|
||||
* *
|
||||
*---------------------------------------------------------------------------*
|
||||
* Beschreibung: VESA-Treiber ueber 16-Bit BIOS. *
|
||||
* *
|
||||
* Autor: Michael Schoettner, HHU, 18.3.2017 *
|
||||
*****************************************************************************/
|
||||
|
||||
#include "VESA.h"
|
||||
#include "device/bios/BIOS.h"
|
||||
|
||||
// Informationen ueber einen VESA-Grafikmodus
|
||||
// (siehe http://wiki.osdev.org/VESA_Video_Modes)
|
||||
struct VbeModeInfoBlock {
|
||||
unsigned short attributes;
|
||||
unsigned char winA, winB;
|
||||
unsigned short granularity;
|
||||
unsigned short winsize;
|
||||
unsigned short segmentA, segmentB;
|
||||
unsigned short realFctPtr[2];
|
||||
unsigned short pitch; // Bytes pro Scanline
|
||||
|
||||
unsigned short Xres, Yres;
|
||||
unsigned char Wchar, Ychar, planes, bpp, banks;
|
||||
unsigned char memory_model, bank_size, image_pages;
|
||||
unsigned char reserved0;
|
||||
|
||||
unsigned char red_mask, red_position;
|
||||
unsigned char green_mask, green_position;
|
||||
unsigned char blue_mask, blue_position;
|
||||
unsigned char rsv_mask, rsv_position;
|
||||
unsigned char directcolor_attributes;
|
||||
|
||||
unsigned int physbase; // Adresse des Linear-Framebuffers
|
||||
unsigned int OffScreenMemOffset;
|
||||
unsigned short OffScreenMemSize;
|
||||
} __attribute__((packed));
|
||||
|
||||
// Informationen ueber die Grafikkarte
|
||||
// (siehe http://wiki.osdev.org/VESA_Video_Modes)
|
||||
struct VbeInfoBlock {
|
||||
char VbeSignature[4]; // == "VESA"
|
||||
unsigned short VbeVersion; // == 0x0300 for VBE 3.0
|
||||
unsigned short OemStringPtr[2]; // isa vbeFarPtr
|
||||
unsigned char Capabilities[4];
|
||||
unsigned short VideoModePtr[2]; // isa vbeFarPtr
|
||||
unsigned short TotalMemory; // as # of 64KB blocks
|
||||
} __attribute__((packed));
|
||||
|
||||
/*****************************************************************************
|
||||
* Methode: VESA::initTextMode *
|
||||
*---------------------------------------------------------------------------*
|
||||
* Beschreibung: Schalter in den Text-Modus 80x25 Zeichen. *
|
||||
*****************************************************************************/
|
||||
void VESA::initTextMode() {
|
||||
BC_params->AX = 0x4f02; // SVFA BIOS, init mode
|
||||
BC_params->BX = 0x4003; // 80x25
|
||||
BIOS::Int(0x10);
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* Methode: VESA::initGraphicMode *
|
||||
*---------------------------------------------------------------------------*
|
||||
* Parameter: Nummer des Grafikmodus (siehe VESA.h) *
|
||||
* *
|
||||
* Beschreibung: Bestimmten Grafikmodus einschalten. Dies wird durch *
|
||||
* einen Aufruf des BIOS gemacht. *
|
||||
*****************************************************************************/
|
||||
bool VESA::initGraphicMode(unsigned short mode) {
|
||||
|
||||
// Alle Grafikmodi abfragen
|
||||
BC_params->AX = 0x4F00;
|
||||
BC_params->ES = RETURN_MEM >> 4;
|
||||
BC_params->DI = RETURN_MEM & 0xF;
|
||||
BIOS::Int(0x10);
|
||||
|
||||
VbeInfoBlock* ib = reinterpret_cast<VbeInfoBlock*>(RETURN_MEM);
|
||||
|
||||
// Signaturen pruefen
|
||||
if (BC_params->AX != 0x004F) {
|
||||
log.error() << "VESA wird nicht unterstuetzt." << endl;
|
||||
return false;
|
||||
}
|
||||
if (ib->VbeSignature[0] != 'V' || ib->VbeSignature[1] != 'E' ||
|
||||
ib->VbeSignature[2] != 'S' || ib->VbeSignature[3] != 'A') {
|
||||
log.error() << "VESA wird nicht unterstuetzt." << endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
// kout << "TotalVideoMemory: " << ((ib->TotalMemory*65536) / (1024*1024)) << " MB" << endl;
|
||||
|
||||
// Gewuenschten Grafikmodus aus Antwort suchen
|
||||
unsigned short* modePtr = reinterpret_cast<unsigned short*>((ib->VideoModePtr[1] << 4) + ib->VideoModePtr[0]);
|
||||
for (int i = 0; modePtr[i] != 0xFFFF; ++i) {
|
||||
// Gewuenschter Grafikmodus gefunden?
|
||||
if (modePtr[i] == mode) {
|
||||
VbeModeInfoBlock* minf = reinterpret_cast<VbeModeInfoBlock*>(RETURN_MEM);
|
||||
|
||||
// Weitere Infos ueber diesen Grafikmodus abfragen
|
||||
BC_params->AX = 0x4F01;
|
||||
BC_params->CX = mode;
|
||||
BC_params->ES = RETURN_MEM >> 4;
|
||||
BC_params->DI = RETURN_MEM & 0xF;
|
||||
BIOS::Int(0x10);
|
||||
|
||||
// Text-Modi 0-3 haben keinen LFB
|
||||
if (mode > 3 && (minf->attributes & 0x90) == 0) {
|
||||
log.error() << "Grafikmodus bietet keinen linearen Framebuffer." << endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
mode_nr = mode;
|
||||
xres = minf->Xres;
|
||||
yres = minf->Yres;
|
||||
bpp = static_cast<int>(minf->bpp);
|
||||
lfb = minf->physbase;
|
||||
|
||||
hfb = reinterpret_cast<unsigned int>(new char[xres * yres * bpp / 8]);
|
||||
|
||||
// Grafikmodus einschalten
|
||||
BC_params->AX = 0x4f02; // SVFA BIOS, init mode
|
||||
BC_params->BX = mode;
|
||||
BIOS::Int(0x10);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
log.error() << "Grafikmodus nicht gefunden." << endl;
|
||||
return false;
|
||||
}
|
42
src/device/graphics/VESA.h
Normal file
42
src/device/graphics/VESA.h
Normal file
@ -0,0 +1,42 @@
|
||||
/*****************************************************************************
|
||||
* *
|
||||
* V E S A *
|
||||
* *
|
||||
*---------------------------------------------------------------------------*
|
||||
* Beschreibung: VESA-Treiber ueber 16-Bit BIOS. *
|
||||
* *
|
||||
* Autor: Michael Schoettner, HHU, 19.5.2022 *
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef VESA_include__
|
||||
#define VESA_include__
|
||||
|
||||
#include "LFBgraphics.h"
|
||||
#include "kernel/log/Logger.h"
|
||||
|
||||
// Ausgewaehlte Grafikmodi mit Mode-Nummer
|
||||
constexpr const unsigned int MODE_640_480_16BITS = 0x111;
|
||||
constexpr const unsigned int MODE_640_480_24BITS = 0x112;
|
||||
constexpr const unsigned int MODE_800_600_16BITS = 0x114;
|
||||
constexpr const unsigned int MODE_800_600_24BITS = 0x115;
|
||||
constexpr const unsigned int MODE_1024_768_16BITS = 0x117;
|
||||
constexpr const unsigned int MODE_1024_768_24BITS = 0x118;
|
||||
|
||||
class VESA : public LFBgraphics {
|
||||
private:
|
||||
int mode_nr; // Nummer des Modus
|
||||
NamedLogger log;
|
||||
|
||||
public:
|
||||
VESA(const VESA& copy) = delete; // Verhindere Kopieren
|
||||
|
||||
VESA() : log("VESA") {}
|
||||
|
||||
// Can't make singleton because atexit
|
||||
|
||||
// Bestimmten Grafikmodus einschalten
|
||||
bool initGraphicMode(unsigned short mode);
|
||||
static void initTextMode();
|
||||
};
|
||||
|
||||
#endif
|
117
src/device/hid/Key.h
Executable file
117
src/device/hid/Key.h
Executable file
@ -0,0 +1,117 @@
|
||||
/*****************************************************************************
|
||||
* *
|
||||
* K E Y *
|
||||
* *
|
||||
*---------------------------------------------------------------------------*
|
||||
* Beschreibung: Taste, bestehend aus ASCII-, Scan-Code und Modifier-Bits.*
|
||||
* *
|
||||
* Autor: Olaf Spinczyk, TU Dortmund *
|
||||
*****************************************************************************/
|
||||
#ifndef Key_include__
|
||||
#define Key_include__
|
||||
|
||||
class Key {
|
||||
// Kopieren erlaubt!
|
||||
|
||||
unsigned char asc; // ASCII code
|
||||
unsigned char scan; // scan code
|
||||
unsigned char modi; // modifier
|
||||
|
||||
// Bit-Masken fuer die Modifier-Tasten
|
||||
struct mbit {
|
||||
enum {
|
||||
shift = 1,
|
||||
alt_left = 2,
|
||||
alt_right = 4,
|
||||
ctrl_left = 8,
|
||||
ctrl_right = 16,
|
||||
caps_lock = 32,
|
||||
num_lock = 64,
|
||||
scroll_lock = 128
|
||||
};
|
||||
};
|
||||
|
||||
public:
|
||||
// DEFAULT-KONSTRUKTOR: setzt ASCII, Scancode und Modifier auf 0
|
||||
// und bezeichnet so einen ungueltigen Tastencode
|
||||
Key() : asc(0), scan(0), modi(0) {}
|
||||
|
||||
// VALID: mit Scancode = 0 werden ungueltige Tasten gekennzeichnet.
|
||||
bool valid() const { return scan != 0; }
|
||||
|
||||
// INVALIDATE: setzt den Scancode auf Null und sorgt somit fuer einen
|
||||
// ungueltigen Tastencode.
|
||||
void invalidate() { scan = 0; }
|
||||
|
||||
// ASCII, SCANCODE: Setzen und Abfragen von Ascii und Scancode
|
||||
void ascii(unsigned char a) { asc = a; }
|
||||
void scancode(unsigned char s) { scan = s; }
|
||||
unsigned char ascii() const { return asc; }
|
||||
unsigned char scancode() const { return scan; }
|
||||
|
||||
//
|
||||
// Funktionen zum Setzen und Loeschen von SHIFT, ALT, CTRL usw.
|
||||
//
|
||||
void shift(bool pressed) {
|
||||
modi = pressed ? modi | mbit::shift : modi & ~mbit::shift;
|
||||
}
|
||||
|
||||
void alt_left(bool pressed) {
|
||||
modi = pressed ? modi | mbit::alt_left : modi & ~mbit::alt_left;
|
||||
}
|
||||
|
||||
void alt_right(bool pressed) {
|
||||
modi = pressed ? modi | mbit::alt_right : modi & ~mbit::alt_right;
|
||||
}
|
||||
|
||||
void ctrl_left(bool pressed) {
|
||||
modi = pressed ? modi | mbit::ctrl_left : modi & ~mbit::ctrl_left;
|
||||
}
|
||||
|
||||
void ctrl_right(bool pressed) {
|
||||
modi = pressed ? modi | mbit::ctrl_right : modi & ~mbit::ctrl_right;
|
||||
}
|
||||
|
||||
void caps_lock(bool pressed) {
|
||||
modi = pressed ? modi | mbit::caps_lock : modi & ~mbit::caps_lock;
|
||||
}
|
||||
|
||||
void num_lock(bool pressed) {
|
||||
modi = pressed ? modi | mbit::num_lock : modi & ~mbit::num_lock;
|
||||
}
|
||||
|
||||
void scroll_lock(bool pressed) {
|
||||
modi = pressed ? modi | mbit::scroll_lock : modi & ~mbit::scroll_lock;
|
||||
}
|
||||
|
||||
//
|
||||
// Funktionen zum Abfragen von SHIFT, ALT, CTRL usw.
|
||||
//
|
||||
bool shift() const { return (modi & mbit::shift) != 0; }
|
||||
bool alt_left() const { return (modi & mbit::alt_left) != 0; }
|
||||
bool alt_right() const { return (modi & mbit::alt_right) != 0; }
|
||||
bool ctrl_left() const { return (modi & mbit::ctrl_left) != 0; }
|
||||
bool ctrl_right() const { return (modi & mbit::ctrl_right) != 0; }
|
||||
bool caps_lock() const { return (modi & mbit::caps_lock) != 0; }
|
||||
bool num_lock() const { return (modi & mbit::num_lock) != 0; }
|
||||
bool scroll_lock() const { return (modi & mbit::scroll_lock) != 0; }
|
||||
bool alt() const { return alt_left() || alt_right(); }
|
||||
bool ctrl() const { return ctrl_left() || ctrl_right(); }
|
||||
|
||||
operator char() const { return static_cast<char>(asc); }
|
||||
|
||||
// Scan-Codes einiger spezieller Tasten
|
||||
struct scan {
|
||||
enum {
|
||||
f1 = 0x3b,
|
||||
del = 0x53,
|
||||
up = 72,
|
||||
down = 80,
|
||||
left = 75,
|
||||
right = 77,
|
||||
div = 8
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
#endif
|
349
src/device/hid/Keyboard.cc
Executable file
349
src/device/hid/Keyboard.cc
Executable file
@ -0,0 +1,349 @@
|
||||
/*****************************************************************************
|
||||
* *
|
||||
* K E Y B O A R D *
|
||||
* *
|
||||
*---------------------------------------------------------------------------*
|
||||
* Beschreibung: Treiber für den Tastaturcontroller des PCs. *
|
||||
* *
|
||||
* Autor: Olaf Spinczyk, TU Dortmund *
|
||||
*****************************************************************************/
|
||||
|
||||
#include "Keyboard.h"
|
||||
#include "kernel/system/Globals.h"
|
||||
#include "Key.h"
|
||||
|
||||
const IOport Keyboard::ctrl_port(0x64);
|
||||
const IOport Keyboard::data_port(0x60);
|
||||
|
||||
/* Tabellen fuer ASCII-Codes (Klassenvariablen) intiialisieren */
|
||||
|
||||
constexpr const unsigned char Keyboard::normal_tab[] = {
|
||||
0, 0, '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', 225, 39, '\b',
|
||||
0, 'q', 'w', 'e', 'r', 't', 'z', 'u', 'i', 'o', 'p', 129, '+', '\n',
|
||||
0, 'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', 148, 132, '^', 0, '#',
|
||||
'y', 'x', 'c', 'v', 'b', 'n', 'm', ',', '.', '-', 0,
|
||||
'*', 0, ' ', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, '-',
|
||||
0, 0, 0, '+', 0, 0, 0, 0, 0, 0, 0, '<', 0, 0};
|
||||
|
||||
constexpr const unsigned char Keyboard::shift_tab[] = {
|
||||
0, 0, '!', '"', 21, '$', '%', '&', '/', '(', ')', '=', '?', 96, 0,
|
||||
0, 'Q', 'W', 'E', 'R', 'T', 'Z', 'U', 'I', 'O', 'P', 154, '*', 0,
|
||||
0, 'A', 'S', 'D', 'F', 'G', 'H', 'J', 'K', 'L', 153, 142, 248, 0, 39,
|
||||
'Y', 'X', 'C', 'V', 'B', 'N', 'M', ';', ':', '_', 0,
|
||||
0, 0, ' ', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, '>', 0, 0};
|
||||
|
||||
constexpr const unsigned char Keyboard::alt_tab[] = {
|
||||
0, 0, 0, 253, 0, 0, 0, 0, '{', '[', ']', '}', '\\', 0, 0,
|
||||
0, '@', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, '~', 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 230, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, '|', 0, 0};
|
||||
|
||||
constexpr const unsigned char Keyboard::asc_num_tab[] = {
|
||||
'7', '8', '9', '-', '4', '5', '6', '+', '1', '2', '3', '0', ','};
|
||||
|
||||
constexpr const unsigned char Keyboard::scan_num_tab[] = {
|
||||
8, 9, 10, 53, 5, 6, 7, 27, 2, 3, 4, 11, 51};
|
||||
|
||||
/*****************************************************************************
|
||||
* Methode: Keyboard::key_decoded *
|
||||
*---------------------------------------------------------------------------*
|
||||
* Beschreibung: Interpretiert die Make- und Break-Codes der Tastatur. *
|
||||
* *
|
||||
* Rueckgabewert: true bedeutet, dass das Zeichen komplett ist *
|
||||
* false es fehlen noch Make- oder Break-Codes. *
|
||||
*****************************************************************************/
|
||||
bool Keyboard::key_decoded() {
|
||||
bool done = false;
|
||||
|
||||
// Die Tasten, die bei der MF II Tastatur gegenueber der aelteren
|
||||
// AT Tastatur hinzugekommen sind, senden immer erst eines von zwei
|
||||
// moeglichen Prefix Bytes.
|
||||
if (code == prefix1 || code == prefix2) {
|
||||
prefix = code;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Das Loslassen einer Taste ist eigentlich nur bei den "Modifier" Tasten
|
||||
// SHIFT, CTRL und ALT von Interesse, bei den anderen kann der Break-Code
|
||||
// ignoriert werden.
|
||||
if (code & break_bit) {
|
||||
code &= ~break_bit; // Der Break-Code einer Taste ist gleich dem
|
||||
// Make-Code mit gesetzten break_bit.
|
||||
switch (code) {
|
||||
case 42:
|
||||
case 54:
|
||||
gather.shift(false);
|
||||
break;
|
||||
case 56:
|
||||
if (prefix == prefix1) {
|
||||
gather.alt_right(false);
|
||||
} else {
|
||||
gather.alt_left(false);
|
||||
}
|
||||
break;
|
||||
case 29:
|
||||
if (prefix == prefix1) {
|
||||
gather.ctrl_right(false);
|
||||
} else {
|
||||
gather.ctrl_left(false);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// Ein Prefix gilt immer nur fuer den unmittelbar nachfolgenden Code.
|
||||
// Also ist es jetzt abgehandelt.
|
||||
prefix = 0;
|
||||
|
||||
// Mit einem Break-Code kann man nichts anfangen, also false liefern.
|
||||
return false;
|
||||
}
|
||||
|
||||
// Eine Taste wurde gedrueckt. Bei den Modifier Tasten wie SHIFT, ALT,
|
||||
// NUM_LOCK etc. wird nur der interne Zustand geaendert. Durch den
|
||||
// Rueckgabewert 'false' wird angezeigt, dass die Tastatureingabe noch
|
||||
// nicht abgeschlossen ist. Bei den anderen Tasten werden ASCII
|
||||
// und Scancode eingetragen und ein 'true' fuer eine erfolgreiche
|
||||
// Tastaturabfrage zurueckgegeben, obwohl genaugenommen noch der Break-
|
||||
// code der Taste fehlt.
|
||||
|
||||
switch (code) {
|
||||
case 42:
|
||||
case 54:
|
||||
gather.shift(true);
|
||||
break;
|
||||
case 56:
|
||||
if (prefix == prefix1) {
|
||||
gather.alt_right(true);
|
||||
} else {
|
||||
gather.alt_left(true);
|
||||
}
|
||||
break;
|
||||
case 29:
|
||||
if (prefix == prefix1) {
|
||||
gather.ctrl_right(true);
|
||||
} else {
|
||||
gather.ctrl_left(true);
|
||||
}
|
||||
break;
|
||||
case 58:
|
||||
gather.caps_lock(!gather.caps_lock());
|
||||
set_led(led::caps_lock, gather.caps_lock());
|
||||
break;
|
||||
case 70:
|
||||
gather.scroll_lock(!gather.scroll_lock());
|
||||
set_led(led::scroll_lock, gather.scroll_lock());
|
||||
break;
|
||||
case 69: // Numlock oder Pause ?
|
||||
if (gather.ctrl_left()) { // Pause Taste
|
||||
// Auf alten Tastaturen konnte die Pause-Funktion wohl nur
|
||||
// ueber Ctrl+NumLock erreicht werden. Moderne MF-II Tastaturen
|
||||
// senden daher diese Codekombination, wenn Pause gemeint ist.
|
||||
// Die Pause Taste liefert zwar normalerweise keinen ASCII-
|
||||
// Code, aber Nachgucken schadet auch nicht. In jedem Fall ist
|
||||
// die Taste nun komplett.
|
||||
get_ascii_code();
|
||||
done = true;
|
||||
} else { // NumLock
|
||||
gather.num_lock(!gather.num_lock());
|
||||
set_led(led::num_lock, gather.num_lock());
|
||||
}
|
||||
break;
|
||||
|
||||
default: // alle anderen Tasten
|
||||
// ASCII-Codes aus den entsprechenden Tabellen auslesen, fertig.
|
||||
get_ascii_code();
|
||||
done = true;
|
||||
}
|
||||
|
||||
// Ein Prefix gilt immer nur fuer den unmittelbar nachfolgenden Code.
|
||||
// Also ist es jetzt abgehandelt.
|
||||
prefix = 0;
|
||||
|
||||
return done;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* Methode: Keyboard::get_ascii_code *
|
||||
*---------------------------------------------------------------------------*
|
||||
* Beschreibung: Ermittelt anhand von Tabellen aus dem Scancode und den *
|
||||
* gesetzten Modifier-Bits den ASCII-Code der Taste. *
|
||||
*****************************************************************************/
|
||||
void Keyboard::get_ascii_code() {
|
||||
// Sonderfall Scancode 53: Dieser Code wird sowohl von der Minustaste
|
||||
// des normalen Tastaturbereichs, als auch von der Divisionstaste des
|
||||
// Ziffernblocks gesendet. Damit in beiden Faellen ein Code heraus-
|
||||
// kommt, der der Aufschrift entspricht, muss im Falle des Ziffern-
|
||||
// blocks eine Umsetzung auf den richtigen Code der Divisionstaste
|
||||
// erfolgen.
|
||||
if (code == 53 && prefix == prefix1) { // Divisionstaste des Ziffernblocks
|
||||
gather.ascii('/');
|
||||
gather.scancode(Key::scan::div);
|
||||
}
|
||||
|
||||
// Anhand der Modifierbits muss die richtige Tabelle ausgewaehlt
|
||||
// werden. Der Einfachheit halber hat NumLock Vorrang vor Alt,
|
||||
// Shift und CapsLock. Fuer Ctrl gibt es keine eigene Tabelle
|
||||
else if (gather.num_lock() && !prefix && code >= 71 && code <= 83) {
|
||||
// Bei eingeschaltetem NumLock und der Betaetigung einer der
|
||||
// Tasten des separaten Ziffernblocks (Codes 71-83), sollen
|
||||
// nicht die Scancodes der Cursortasten, sondern ASCII- und
|
||||
// Scancodes der ensprechenden Zifferntasten geliefert werden.
|
||||
// Die Tasten des Cursorblocks (prefix == prefix1) sollen
|
||||
// natuerlich weiterhin zur Cursorsteuerung genutzt werden
|
||||
// koennen. Sie senden dann uebrigens noch ein Shift, aber das
|
||||
// sollte nicht weiter stoeren.
|
||||
gather.ascii(asc_num_tab[code - 71]);
|
||||
gather.scancode(scan_num_tab[code - 71]);
|
||||
} else if (gather.alt_right()) {
|
||||
gather.ascii(alt_tab[code]);
|
||||
gather.scancode(code);
|
||||
} else if (gather.shift()) {
|
||||
gather.ascii(shift_tab[code]);
|
||||
gather.scancode(code);
|
||||
} else if (gather.caps_lock()) {
|
||||
// Die Umschaltung soll nur bei Buchstaben gelten
|
||||
if ((code >= 16 && code <= 26) || (code >= 30 && code <= 40) || (code >= 44 && code <= 50)) {
|
||||
gather.ascii(shift_tab[code]);
|
||||
gather.scancode(code);
|
||||
} else {
|
||||
gather.ascii(normal_tab[code]);
|
||||
gather.scancode(code);
|
||||
}
|
||||
} else {
|
||||
gather.ascii(normal_tab[code]);
|
||||
gather.scancode(code);
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* Konstruktor: Keyboard::Keyboard *
|
||||
*---------------------------------------------------------------------------*
|
||||
* Beschreibung: Initialisierung der Tastatur: alle LEDs werden ausge- *
|
||||
* schaltet und die Wiederholungsrate auf maximale *
|
||||
* Geschwindigkeit eingestellt. *
|
||||
*****************************************************************************/
|
||||
Keyboard::Keyboard() {
|
||||
// alle LEDs ausschalten (bei vielen PCs ist NumLock nach dem Booten an)
|
||||
set_led(led::caps_lock, false);
|
||||
set_led(led::scroll_lock, false);
|
||||
set_led(led::num_lock, false);
|
||||
|
||||
// maximale Geschwindigkeit, minimale Verzoegerung
|
||||
set_repeat_rate(0, 0);
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* Methode: Keyboard::key_hit *
|
||||
*---------------------------------------------------------------------------*
|
||||
* Beschreibung: Diese Methode soll einen Tastendruck zurueckliefern. *
|
||||
* Hierzu soll die Tastatur in einer Schleife "gepollt" *
|
||||
* werden, bis ein Zeichen eingegebn wurde. *
|
||||
* *
|
||||
* Das Byte von der Tastatur soll in dem Attribut 'code' *
|
||||
* (siehe Keyboard.h) gespeichert werden. Die Dekodierung *
|
||||
* soll mithilfe der vorgegebenen Funktion 'key_decoded' *
|
||||
* erfolgen. *
|
||||
* *
|
||||
* Rückgabewert: Wenn der Tastendruck abgeschlossen ist und ein Scancode, *
|
||||
* sowie gegebenenfalls ein ASCII-Code emittelt werden *
|
||||
* konnte, werden diese in 'gather' (siehe Keyboard.h) *
|
||||
* zurueckgeliefert. Anderenfalls liefert key_hit () einen *
|
||||
* ungueltigen Wert zurueck, was mit Key::valid () *
|
||||
* ueberprueft werden kann. *
|
||||
*****************************************************************************/
|
||||
Key Keyboard::key_hit() {
|
||||
Key invalid; // nicht explizit initialisierte Tasten sind ungueltig
|
||||
|
||||
/* Hier muss Code eingefuegt werden. */
|
||||
|
||||
bool outbyte;
|
||||
do {
|
||||
outbyte = ctrl_port.inb() & outb;
|
||||
} while (!outbyte);
|
||||
|
||||
// Ignore PS2 Mouse
|
||||
bool auxbyte = ctrl_port.inb() & auxb;
|
||||
if (auxbyte) {
|
||||
return invalid;
|
||||
}
|
||||
|
||||
code = data_port.inb();
|
||||
if (key_decoded()) {
|
||||
return gather;
|
||||
}
|
||||
|
||||
return invalid;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* Methode: Keyboard::reboot *
|
||||
*---------------------------------------------------------------------------*
|
||||
* Beschreibung: Fuehrt einen Neustart des Rechners durch. *
|
||||
*****************************************************************************/
|
||||
void Keyboard::reboot() {
|
||||
int status;
|
||||
|
||||
// Dem BIOS mitteilen, dass das Reset beabsichtigt war
|
||||
// und kein Speichertest durchgefuehrt werden muss.
|
||||
*reinterpret_cast<unsigned short*>(0x472) = 0x1234;
|
||||
|
||||
// Der Tastaturcontroller soll das Reset ausloesen.
|
||||
do {
|
||||
status = ctrl_port.inb(); // warten, bis das letzte Kommando
|
||||
} while ((status & inpb) != 0); // verarbeitet wurde.
|
||||
ctrl_port.outb(cpu_reset); // Reset
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* Methode: Keyboard::set_repeat_rate *
|
||||
*---------------------------------------------------------------------------*
|
||||
* Beschreibung: Einstellen der Wiederholungsrate der Tastatur. *
|
||||
* *
|
||||
* Parameter: *
|
||||
* delay: Bestimmt, wie lange eine Taste gedrueckt werden muss, *
|
||||
* bevor die Wiederholung einsetzt. Erlaubt sind Werte *
|
||||
* zw. 0 (minimale Wartezeit) und 3 (maximale Wartezeit). *
|
||||
* speed: Bestimmt, wie schnell die Tastencodes aufeinander folgen *
|
||||
* sollen. Erlaubt sind Werte zwischen 0 (sehr schnell) *
|
||||
* und 31 (sehr langsam). *
|
||||
*****************************************************************************/
|
||||
void Keyboard::set_repeat_rate(int speed, int delay) {
|
||||
|
||||
/* Hier muss Code eingefuegt werden. */
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* Methode: Keyboard::set_led *
|
||||
*---------------------------------------------------------------------------*
|
||||
* Beschreibung: Setzt oder loescht die angegebene Leuchtdiode. *
|
||||
* *
|
||||
* Parameter: *
|
||||
* led: Welche LED? (caps_lock, num_lock, scroll_lock) *
|
||||
* on: 0 = aus, 1 = an *
|
||||
*****************************************************************************/
|
||||
void Keyboard::set_led(char led, bool on) {
|
||||
|
||||
/* Hier muss Code eingefuegt werden. */
|
||||
}
|
||||
|
||||
// Registriert die Tastatur ISR im IntDispatcher
|
||||
// und erlaubt den keyboard interrupt im PIC
|
||||
void Keyboard::plugin() {
|
||||
intdis.assign(IntDispatcher::keyboard, *this);
|
||||
PIC::allow(PIC::keyboard);
|
||||
}
|
||||
|
||||
void Keyboard::trigger() {
|
||||
Key key = key_hit();
|
||||
// lastkey = key.ascii();
|
||||
|
||||
// NOTE: My keyboard has no delete key...
|
||||
if (key.ctrl_left() && key.alt_left() && static_cast<char>(key) == 'r') {
|
||||
reboot();
|
||||
} else if (key != 0) {
|
||||
kevman.broadcast(key); // Send key to all subscribed threads
|
||||
}
|
||||
}
|
100
src/device/hid/Keyboard.h
Executable file
100
src/device/hid/Keyboard.h
Executable file
@ -0,0 +1,100 @@
|
||||
/*****************************************************************************
|
||||
* *
|
||||
* K E Y B O A R D *
|
||||
* *
|
||||
*---------------------------------------------------------------------------*
|
||||
* Beschreibung: Treiber für den Tastaturcontroller des PCs. *
|
||||
* *
|
||||
* Autor: Olaf Spinczyk, TU Dortmund *
|
||||
* Modifikationen, Michael Schoettner, 2.6.2022 *
|
||||
*****************************************************************************/
|
||||
#ifndef Keyboard_include__
|
||||
#define Keyboard_include__
|
||||
|
||||
#include "Key.h"
|
||||
#include "kernel/interrupt/ISR.h"
|
||||
#include "device/port/IOport.h"
|
||||
|
||||
class Keyboard : public ISR {
|
||||
private:
|
||||
unsigned char code; // Byte von Tastatur
|
||||
unsigned char prefix; // Prefix von Tastatur
|
||||
Key gather; // letzter dekodierter Key
|
||||
char leds; // Zustand LEDs
|
||||
|
||||
// Benutzte Ports des Tastaturcontrollers
|
||||
static const IOport ctrl_port; // Status- (R) u. Steuerregister (W)
|
||||
static const IOport data_port; // Ausgabe- (R) u. Eingabepuffer (W)
|
||||
|
||||
// Bits im Statusregister
|
||||
enum { outb = 0x01,
|
||||
inpb = 0x02,
|
||||
auxb = 0x20 };
|
||||
|
||||
// Kommandos an die Tastatur
|
||||
struct kbd_cmd {
|
||||
enum { set_led = 0xed,
|
||||
set_speed = 0xf3 };
|
||||
};
|
||||
enum { cpu_reset = 0xfe };
|
||||
|
||||
// Namen der LEDs
|
||||
struct led {
|
||||
enum { caps_lock = 4,
|
||||
num_lock = 2,
|
||||
scroll_lock = 1 };
|
||||
};
|
||||
|
||||
// Antworten der Tastatur
|
||||
struct kbd_reply {
|
||||
enum { ack = 0xfa };
|
||||
};
|
||||
|
||||
// Konstanten fuer die Tastaturdekodierung
|
||||
enum { break_bit = 0x80,
|
||||
prefix1 = 0xe0,
|
||||
prefix2 = 0xe1 };
|
||||
|
||||
// Klassenvariablen
|
||||
static const unsigned char normal_tab[];
|
||||
static const unsigned char shift_tab[];
|
||||
static const unsigned char alt_tab[];
|
||||
static const unsigned char asc_num_tab[];
|
||||
static const unsigned char scan_num_tab[];
|
||||
|
||||
// Interpretiert die Make und Break-Codes der Tastatur.
|
||||
bool key_decoded();
|
||||
|
||||
// Ermittelt anhand von Tabellen den ASCII-Code.
|
||||
void get_ascii_code();
|
||||
|
||||
// Tastaturabfrage (vorerst Polling)
|
||||
Key key_hit();
|
||||
|
||||
public:
|
||||
Keyboard(const Keyboard& copy) = delete; // Verhindere Kopieren
|
||||
|
||||
// Initialisierung der Tastatur.
|
||||
Keyboard();
|
||||
|
||||
// ~Keyboard() override = default;
|
||||
|
||||
// unsigned int lastkey; // speichert den ASCII-Code der zuletzt gedrückten Taste
|
||||
|
||||
// Fuehrt einen Neustart des Rechners durch.
|
||||
static void reboot();
|
||||
|
||||
// Einstellen der Wiederholungsrate der Tastatur.
|
||||
void set_repeat_rate(int speed, int delay);
|
||||
|
||||
// Setzt oder loescht die angegebene Leuchtdiode.
|
||||
void set_led(char led, bool on);
|
||||
|
||||
// Aktivierung der Unterbrechungen fuer die Tastatur
|
||||
void plugin();
|
||||
|
||||
// Unterbrechnungsroutine der Tastatur.
|
||||
void trigger() override;
|
||||
};
|
||||
|
||||
#endif
|
105
src/device/interrupt/PIC.cc
Executable file
105
src/device/interrupt/PIC.cc
Executable file
@ -0,0 +1,105 @@
|
||||
/*****************************************************************************
|
||||
* *
|
||||
* P I C *
|
||||
* *
|
||||
*---------------------------------------------------------------------------*
|
||||
* Beschreibung: Mit Hilfe des PICs koennen Hardware-Interrupts (IRQs) *
|
||||
* einzeln zugelassen oder unterdrueckt werden. Auf diese *
|
||||
* Weise wird also bestimmt, ob die Unterbrechung eines *
|
||||
* Geraetes ueberhaupt an den Prozessor weitergegeben wird. *
|
||||
* Selbst dann erfolgt eine Aktivierung der Unterbrechungs- *
|
||||
* routine nur, wenn der Prozessor bereit ist, auf Unter- *
|
||||
* brechungen zu reagieren. Dies kann mit Hilfe der Klasse *
|
||||
* CPU festgelegt werden. *
|
||||
* *
|
||||
* Autor: Olaf Spinczyk, TU Dortmund *
|
||||
*****************************************************************************/
|
||||
|
||||
#include "PIC.h"
|
||||
|
||||
IOport const PIC::IMR1(0x21); // interrupt mask register von PIC 1
|
||||
IOport const PIC::IMR2(0xa1); // interrupt mask register von PIC 2
|
||||
|
||||
/*****************************************************************************
|
||||
* Methode: PIC::allow *
|
||||
*---------------------------------------------------------------------------*
|
||||
* Beschreibung: Sorgt dafuer, dass der uebergebene IRQ ab sofort durch *
|
||||
* den PIC an den Prozessor weitergereicht wird. Um eine *
|
||||
* Unterbrechungsbehandlung zu ermoeglichen, muss *
|
||||
* zusaetzlich CPU::enable_int() aufgerufen werden. *
|
||||
* *
|
||||
* Parameter: *
|
||||
* irq: IRQ der erlaubt werden soll *
|
||||
*****************************************************************************/
|
||||
void PIC::allow(int irq) {
|
||||
|
||||
/* hier muss Code eingefuegt werden */
|
||||
|
||||
// NOTE: allow sets the bit to 0
|
||||
|
||||
unsigned char IMR;
|
||||
unsigned char mask = ~(0x1 << (irq % 8));
|
||||
if (irq < 8) {
|
||||
// PIC 1
|
||||
IMR = IMR1.inb(); // We don't want to change the other interrupt masks so use this as start value
|
||||
IMR1.outb(IMR & mask);
|
||||
} else {
|
||||
// PIC 2
|
||||
IMR = IMR2.inb();
|
||||
IMR2.outb(IMR & mask);
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* Methode: PIC::forbid *
|
||||
*---------------------------------------------------------------------------*
|
||||
* Beschreibung: Unterdrueckt mit Hilfe des PICs einen bestimmten IRQ. *
|
||||
* *
|
||||
* Parameter: *
|
||||
* interrupt: IRQ der maskiert werden soll *
|
||||
*****************************************************************************/
|
||||
void PIC::forbid(int irq) {
|
||||
|
||||
/* hier muss Code eingefuegt werden */
|
||||
|
||||
// NOTE: forbid sets the bit to 1
|
||||
|
||||
unsigned char IMR;
|
||||
unsigned char mask = 0x1 << (irq % 8);
|
||||
if (irq < 8) {
|
||||
// PIC 1
|
||||
IMR = IMR1.inb(); // We don't want to change the other interrupt masks so use this as start value
|
||||
IMR1.outb(IMR | mask);
|
||||
} else {
|
||||
// PIC 2
|
||||
IMR = IMR2.inb();
|
||||
IMR2.outb(IMR | mask);
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* Methode: PIC::status *
|
||||
*---------------------------------------------------------------------------*
|
||||
* Beschreibung: Liefert den aktuellen Zustand des Maskierbits eines *
|
||||
* bestimmten IRQs. *
|
||||
* *
|
||||
* Parameter: *
|
||||
* irq: IRQ dessen Status erfragt werden soll *
|
||||
*****************************************************************************/
|
||||
bool PIC::status(int irq) {
|
||||
|
||||
/* hier muss Code eingefuegt werden */
|
||||
|
||||
unsigned char IMR;
|
||||
if (irq < 8) {
|
||||
// PIC 1
|
||||
IMR = IMR1.inb();
|
||||
} else {
|
||||
// PIC 2
|
||||
IMR = IMR2.inb();
|
||||
}
|
||||
|
||||
// Use % 8 to account for two PICs
|
||||
unsigned char mask = 0x1 << (irq % 8);
|
||||
return IMR & mask;
|
||||
}
|
51
src/device/interrupt/PIC.h
Executable file
51
src/device/interrupt/PIC.h
Executable file
@ -0,0 +1,51 @@
|
||||
/*****************************************************************************
|
||||
* *
|
||||
* P I C *
|
||||
* *
|
||||
*---------------------------------------------------------------------------*
|
||||
* Beschreibung: Mit Hilfe des PICs koennen Hardware-Interrupts (IRQs) *
|
||||
* einzeln zugelassen oder unterdrueckt werden. Auf diese *
|
||||
* Weise wird also bestimmt, ob die Unterbrechung eines *
|
||||
* Geraetes ueberhaupt an den Prozessor weitergegeben wird. *
|
||||
* Selbst dann erfolgt eine Aktivierung der Unterbrechungs- *
|
||||
* routine nur, wenn der Prozessor bereit ist, auf Unter- *
|
||||
* brechungen zu reagieren. Dies kann mit Hilfe der Klasse *
|
||||
* CPU festgelegt werden. *
|
||||
* *
|
||||
* Autor: Olaf Spinczyk, TU Dortmund *
|
||||
*****************************************************************************/
|
||||
#ifndef PIC_include__
|
||||
#define PIC_include__
|
||||
|
||||
#include "device/port/IOport.h"
|
||||
|
||||
class PIC {
|
||||
private:
|
||||
static const IOport IMR1; // interrupt mask register von PIC 1
|
||||
static const IOport IMR2; // interrupt mask register von PIC 2
|
||||
|
||||
public:
|
||||
PIC(const PIC& copy) = delete; // Verhindere Kopieren
|
||||
|
||||
PIC() = default;
|
||||
|
||||
// Can't make static because atexit
|
||||
|
||||
// IRQ-Nummern von Geraeten
|
||||
enum {
|
||||
timer = 0, // Programmable Interrupt Timer (PIT)
|
||||
keyboard = 1, // Tastatur
|
||||
com1 = 4
|
||||
};
|
||||
|
||||
// Freischalten der Weiterleitung eines IRQs durch den PIC an die CPU
|
||||
static void allow(int irq);
|
||||
|
||||
// Unterdruecken der Weiterleitung eines IRQs durch den PIC an die CPU
|
||||
static void forbid(int irq);
|
||||
|
||||
// Abfragen, ob die Weiterleitung fuer einen bestimmten IRQ unterdrueckt ist
|
||||
static bool status(int interrupt_device);
|
||||
};
|
||||
|
||||
#endif
|
97
src/device/port/IOport.h
Executable file
97
src/device/port/IOport.h
Executable file
@ -0,0 +1,97 @@
|
||||
/*****************************************************************************
|
||||
* *
|
||||
* I O P O R T *
|
||||
* *
|
||||
*---------------------------------------------------------------------------*
|
||||
* Beschreibung: Diese Klasse dient dem Zugriff auf die Ein-/Ausgabe *
|
||||
* Ports des PCs. Beim PC gibt es einen gesonderten I/O- *
|
||||
* Adressraum, der nur mittels der Maschineninstruktionen *
|
||||
* 'in' und 'out' angesprochen werden kann. Ein IOport- *
|
||||
* Objekt wird beim Erstellen an eine Adresse des I/O- *
|
||||
* Adressraums gebunden und kann dann fuer byte- oder *
|
||||
* wortweise Ein- oder Ausgaben verwendet werden. *
|
||||
* *
|
||||
* Autor: Michael Schoettner, 28.8.2016 *
|
||||
*****************************************************************************/
|
||||
#ifndef IOport_include__
|
||||
#define IOport_include__
|
||||
|
||||
class IOport {
|
||||
private:
|
||||
// 16-Bit Adresse im I/O-Adressraum
|
||||
const unsigned short address;
|
||||
|
||||
public:
|
||||
// Konstruktor, speichert Port-Adresse
|
||||
explicit IOport(unsigned short a) : address(a) {};
|
||||
|
||||
// Byteweise Ausgabe eines Wertes ueber einen I/O-Port.
|
||||
void outb(unsigned char val) const {
|
||||
asm volatile("outb %0, %1"
|
||||
:
|
||||
: "a"(val), "Nd"(address));
|
||||
}
|
||||
|
||||
// NOTE: I added this for easier init of COM1 port
|
||||
void outb(unsigned char offset, unsigned char val) const {
|
||||
asm volatile("outb %0, %1"
|
||||
:
|
||||
: "a"(val), "Nd"(static_cast<unsigned short>(address + offset)));
|
||||
}
|
||||
|
||||
// Wortweise Ausgabe eines Wertes ueber einen I/O-Port.
|
||||
void outw(unsigned short val) const {
|
||||
asm volatile("outw %0, %1"
|
||||
:
|
||||
: "a"(val), "Nd"(address));
|
||||
}
|
||||
|
||||
// 32-Bit Ausgabe eines Wertes ueber einen I/O-Port.
|
||||
void outdw(unsigned int val) const {
|
||||
asm volatile("outl %0, %1"
|
||||
:
|
||||
: "a"(val), "Nd"(address));
|
||||
}
|
||||
|
||||
// Byteweises Einlesen eines Wertes ueber einen I/O-Port.
|
||||
unsigned char inb() const {
|
||||
unsigned char ret;
|
||||
|
||||
asm volatile("inb %1, %0"
|
||||
: "=a"(ret)
|
||||
: "Nd"(address));
|
||||
return ret;
|
||||
}
|
||||
|
||||
// NOTE: I added this for COM1 port
|
||||
unsigned char inb(unsigned char offset) const {
|
||||
unsigned char ret;
|
||||
|
||||
asm volatile("inb %1, %0"
|
||||
: "=a"(ret)
|
||||
: "Nd"(static_cast<unsigned short>(address + offset)));
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Wortweises Einlesen eines Wertes ueber einen I/O-Port.
|
||||
unsigned short inw() const {
|
||||
unsigned short ret;
|
||||
|
||||
asm volatile("inw %1, %0"
|
||||
: "=a"(ret)
|
||||
: "Nd"(address));
|
||||
return ret;
|
||||
}
|
||||
|
||||
// 32-Bit Einlesen eines Wertes ueber einen I/O-Port.
|
||||
unsigned int indw() const {
|
||||
unsigned int ret;
|
||||
|
||||
asm volatile("inl %1, %0"
|
||||
: "=a"(ret)
|
||||
: "Nd"(address));
|
||||
return ret;
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
47
src/device/port/SerialOut.cc
Normal file
47
src/device/port/SerialOut.cc
Normal file
@ -0,0 +1,47 @@
|
||||
#include "SerialOut.h"
|
||||
|
||||
const IOport SerialOut::com1(0x3f8);
|
||||
|
||||
SerialOut::SerialOut() {
|
||||
// NOTE: I could add different ports for every register but this was easier as it's that way on OSDev
|
||||
com1.outb(1, 0x00); // Disable all interrupts
|
||||
com1.outb(3, 0x80); // Enable DLAB (set baud rate divisor)
|
||||
com1.outb(0x03); // Set divisor to 3 (lo byte) 38400 baud
|
||||
com1.outb(1, 0x00); // (hi byte)
|
||||
com1.outb(3, 0x03); // 8 bits, no parity, one stop bit
|
||||
com1.outb(2, 0xC7); // Enable FIFO, clear them, with 14-byte threshold
|
||||
com1.outb(4, 0x0B); // IRQs enabled, RTS/DSR set
|
||||
com1.outb(4, 0x1E); // Set in loopback mode, test the serial chip
|
||||
com1.outb(0xAE); // Test serial chip (send byte 0xAE and check if serial returns same byte)
|
||||
|
||||
// Check if serial is faulty (i.e: not same byte as sent)
|
||||
if (com1.inb() == 0xAE) {
|
||||
// If serial is not faulty set it in normal operation mode
|
||||
// (not-loopback with IRQs enabled and OUT#1 and OUT#2 bits enabled)
|
||||
com1.outb(4, 0x0F);
|
||||
}
|
||||
}
|
||||
|
||||
int SerialOut::serial_received() {
|
||||
return com1.inb(5) & 1;
|
||||
}
|
||||
|
||||
int SerialOut::is_transmit_empty() {
|
||||
return com1.inb(5) & 0x20;
|
||||
}
|
||||
|
||||
char SerialOut::read() {
|
||||
while (serial_received() == 0) {}
|
||||
return com1.inb();
|
||||
}
|
||||
|
||||
void SerialOut::write(const char a) {
|
||||
while (is_transmit_empty() == 0) {}
|
||||
com1.outb(a);
|
||||
}
|
||||
|
||||
void SerialOut::write(const bse::string_view a) {
|
||||
for (char current : a) {
|
||||
write(current);
|
||||
}
|
||||
}
|
28
src/device/port/SerialOut.h
Normal file
28
src/device/port/SerialOut.h
Normal file
@ -0,0 +1,28 @@
|
||||
#ifndef SerialOut_Include_H_
|
||||
#define SerialOut_Include_H_
|
||||
|
||||
#include "IOport.h"
|
||||
#include "lib/util/String.h"
|
||||
#include "lib/util/StringView.h"
|
||||
|
||||
// NOTE: I took this code from https://wiki.osdev.org/Serial_Ports
|
||||
|
||||
class SerialOut {
|
||||
private:
|
||||
static const IOport com1;
|
||||
|
||||
static int serial_received();
|
||||
static int is_transmit_empty();
|
||||
|
||||
public:
|
||||
SerialOut();
|
||||
SerialOut(const SerialOut& copy) = delete;
|
||||
|
||||
// Can't make singleton because atexit
|
||||
|
||||
static char read();
|
||||
static void write(char a);
|
||||
static void write(const bse::string_view a);
|
||||
};
|
||||
|
||||
#endif
|
845
src/device/sound/PCSPK.cc
Executable file
845
src/device/sound/PCSPK.cc
Executable file
@ -0,0 +1,845 @@
|
||||
/*****************************************************************************
|
||||
* *
|
||||
* P C S P K *
|
||||
* *
|
||||
*---------------------------------------------------------------------------*
|
||||
* Beschreibung: Mit Hilfe dieser Klasse kann man Toene auf dem *
|
||||
* PC-Lautsprecher ausgeben. *
|
||||
* *
|
||||
* Achtung: Qemu muss mit dem Parameter -soundhw pcspk aufgerufen *
|
||||
* werden. Ansonsten kann man nichts hoeren. *
|
||||
* *
|
||||
* Autor: Michael Schoettner, HHU, 22.9.2016 *
|
||||
*****************************************************************************/
|
||||
|
||||
#include "PCSPK.h"
|
||||
#include "kernel/system/Globals.h"
|
||||
|
||||
const IOport PCSPK::control(0x43);
|
||||
const IOport PCSPK::data2(0x42);
|
||||
const IOport PCSPK::ppi(0x61);
|
||||
|
||||
/*****************************************************************************
|
||||
* Methode: PCSPK::play *
|
||||
*---------------------------------------------------------------------------*
|
||||
* Beschreibung: Ton abspielen. *
|
||||
* *
|
||||
* Rückgabewerte: f: Frequenz des Tons *
|
||||
* len: Laenge des Tons in ms *
|
||||
*****************************************************************************/
|
||||
void PCSPK::play(float f, int len) {
|
||||
int freq = static_cast<int>(f);
|
||||
int cntStart = 1193180 / freq;
|
||||
int status;
|
||||
|
||||
// Zaehler laden
|
||||
control.outb(0xB6); // Zaehler-2 konfigurieren
|
||||
data2.outb(cntStart % 256); // Zaehler-2 laden (Lobyte)
|
||||
data2.outb(cntStart / 256); // Zaehler-2 laden (Hibyte)
|
||||
|
||||
// Lautsprecher einschalten
|
||||
status = static_cast<int>(ppi.inb()); // Status-Register des PPI auslesen
|
||||
ppi.outb(status | 3); // Lautpsrecher Einschalten
|
||||
|
||||
// Pause
|
||||
delay(len);
|
||||
|
||||
// Lautsprecher ausschalten
|
||||
off();
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* Methode: PCSPK::off *
|
||||
*---------------------------------------------------------------------------*
|
||||
* Beschreibung: Lautsprecher ausschalten. *
|
||||
*****************************************************************************/
|
||||
void PCSPK::off() {
|
||||
int status;
|
||||
|
||||
status = static_cast<int>(ppi.inb()); // Status-Register des PPI auslesen
|
||||
ppi.outb((status >> 2) << 2); // Lautsprecher ausschalten
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* Methode: PCSPK::delay *
|
||||
*---------------------------------------------------------------------------*
|
||||
* Beschreibung: Verzoegerung um X ms (in 1ms Schritten; Min. 1ms). *
|
||||
* *
|
||||
* Parameter: time (delay in ms) *
|
||||
*****************************************************************************/
|
||||
inline void PCSPK::delay(int time) {
|
||||
|
||||
/* Hier muess Code eingefuegt werden */
|
||||
|
||||
unsigned long start_time = systime;
|
||||
|
||||
// systime is incremented in 10ms steps
|
||||
while ((systime - start_time) * 10 < time) {}
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* Methode: PCSPK::tetris *
|
||||
*---------------------------------------------------------------------------*
|
||||
* Beschreibung: Tetris Sound, Kévin Rapaille, August 2013 *
|
||||
* https://gist.github.com/XeeX/6220067 *
|
||||
*****************************************************************************/
|
||||
void PCSPK::tetris() {
|
||||
play(658, 125);
|
||||
play(1320, 500);
|
||||
play(990, 250);
|
||||
play(1056, 250);
|
||||
play(1188, 250);
|
||||
play(1320, 125);
|
||||
play(1188, 125);
|
||||
play(1056, 250);
|
||||
play(990, 250);
|
||||
play(880, 500);
|
||||
play(880, 250);
|
||||
play(1056, 250);
|
||||
play(1320, 500);
|
||||
play(1188, 250);
|
||||
play(1056, 250);
|
||||
play(990, 750);
|
||||
play(1056, 250);
|
||||
play(1188, 500);
|
||||
play(1320, 500);
|
||||
play(1056, 500);
|
||||
play(880, 500);
|
||||
play(880, 500);
|
||||
delay(250);
|
||||
play(1188, 500);
|
||||
play(1408, 250);
|
||||
play(1760, 500);
|
||||
play(1584, 250);
|
||||
play(1408, 250);
|
||||
play(1320, 750);
|
||||
play(1056, 250);
|
||||
play(1320, 500);
|
||||
play(1188, 250);
|
||||
play(1056, 250);
|
||||
play(990, 500);
|
||||
play(990, 250);
|
||||
play(1056, 250);
|
||||
play(1188, 500);
|
||||
play(1320, 500);
|
||||
play(1056, 500);
|
||||
play(880, 500);
|
||||
play(880, 500);
|
||||
delay(500);
|
||||
play(1320, 500);
|
||||
play(990, 250);
|
||||
play(1056, 250);
|
||||
play(1188, 250);
|
||||
play(1320, 125);
|
||||
play(1188, 125);
|
||||
play(1056, 250);
|
||||
play(990, 250);
|
||||
play(880, 500);
|
||||
play(880, 250);
|
||||
play(1056, 250);
|
||||
play(1320, 500);
|
||||
play(1188, 250);
|
||||
play(1056, 250);
|
||||
play(990, 750);
|
||||
play(1056, 250);
|
||||
play(1188, 500);
|
||||
play(1320, 500);
|
||||
play(1056, 500);
|
||||
play(880, 500);
|
||||
play(880, 500);
|
||||
delay(250);
|
||||
play(1188, 500);
|
||||
play(1408, 250);
|
||||
play(1760, 500);
|
||||
play(1584, 250);
|
||||
play(1408, 250);
|
||||
play(1320, 750);
|
||||
play(1056, 250);
|
||||
play(1320, 500);
|
||||
play(1188, 250);
|
||||
play(1056, 250);
|
||||
play(990, 500);
|
||||
play(990, 250);
|
||||
play(1056, 250);
|
||||
play(1188, 500);
|
||||
play(1320, 500);
|
||||
play(1056, 500);
|
||||
play(880, 500);
|
||||
play(880, 500);
|
||||
delay(500);
|
||||
play(660, 1000);
|
||||
play(528, 1000);
|
||||
play(594, 1000);
|
||||
play(495, 1000);
|
||||
play(528, 1000);
|
||||
play(440, 1000);
|
||||
play(419, 1000);
|
||||
play(495, 1000);
|
||||
play(660, 1000);
|
||||
play(528, 1000);
|
||||
play(594, 1000);
|
||||
play(495, 1000);
|
||||
play(528, 500);
|
||||
play(660, 500);
|
||||
play(880, 1000);
|
||||
play(838, 2000);
|
||||
play(660, 1000);
|
||||
play(528, 1000);
|
||||
play(594, 1000);
|
||||
play(495, 1000);
|
||||
play(528, 1000);
|
||||
play(440, 1000);
|
||||
play(419, 1000);
|
||||
play(495, 1000);
|
||||
play(660, 1000);
|
||||
play(528, 1000);
|
||||
play(594, 1000);
|
||||
play(495, 1000);
|
||||
play(528, 500);
|
||||
play(660, 500);
|
||||
play(880, 1000);
|
||||
play(838, 2000);
|
||||
off();
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* Methode: PCSPK::tetris *
|
||||
*---------------------------------------------------------------------------*
|
||||
* Beschreibung: Clint, Part of Daft Punk’s Aerodynamic *
|
||||
* https://www.kirrus.co.uk/2010/09/linux-beep-music/ *
|
||||
*****************************************************************************/
|
||||
void PCSPK::aerodynamic() {
|
||||
play(587.3, 122);
|
||||
play(370.0, 122);
|
||||
play(493.9, 122);
|
||||
play(370.0, 122);
|
||||
play(587.3, 122);
|
||||
play(370.0, 122);
|
||||
play(493.9, 122);
|
||||
play(370.0, 122);
|
||||
play(587.3, 122);
|
||||
play(370.0, 122);
|
||||
play(493.9, 122);
|
||||
play(370.0, 122);
|
||||
play(587.3, 122);
|
||||
play(370.0, 122);
|
||||
play(493.9, 122);
|
||||
play(370.0, 122);
|
||||
play(587.3, 122);
|
||||
play(415.3, 122);
|
||||
play(493.9, 122);
|
||||
play(415.3, 122);
|
||||
play(587.3, 122);
|
||||
play(415.3, 122);
|
||||
play(493.9, 122);
|
||||
play(415.3, 122);
|
||||
play(587.3, 122);
|
||||
play(415.3, 122);
|
||||
play(493.9, 122);
|
||||
play(415.3, 122);
|
||||
play(587.3, 122);
|
||||
play(415.3, 122);
|
||||
play(493.9, 122);
|
||||
play(415.3, 122);
|
||||
play(784.0, 122);
|
||||
play(493.9, 122);
|
||||
play(659.3, 122);
|
||||
play(493.9, 122);
|
||||
play(784.0, 122);
|
||||
play(493.9, 122);
|
||||
play(659.3, 122);
|
||||
play(493.9, 122);
|
||||
play(784.0, 122);
|
||||
play(493.9, 122);
|
||||
play(659.3, 122);
|
||||
play(493.9, 122);
|
||||
play(784.0, 122);
|
||||
play(493.9, 122);
|
||||
play(659.3, 122);
|
||||
play(493.9, 122);
|
||||
play(659.3, 122);
|
||||
play(440.0, 122);
|
||||
play(554.4, 122);
|
||||
play(440.0, 122);
|
||||
play(659.3, 122);
|
||||
play(440.0, 122);
|
||||
play(554.4, 122);
|
||||
play(440.0, 122);
|
||||
play(659.3, 122);
|
||||
play(440.0, 122);
|
||||
play(554.4, 122);
|
||||
play(440.0, 122);
|
||||
play(659.3, 122);
|
||||
play(440.0, 122);
|
||||
play(554.4, 122);
|
||||
play(440.0, 122);
|
||||
play(1174.7, 122);
|
||||
play(740.0, 122);
|
||||
play(987.8, 122);
|
||||
play(740.0, 122);
|
||||
play(1174.7, 122);
|
||||
play(740.0, 122);
|
||||
play(987.8, 122);
|
||||
play(740.0, 122);
|
||||
play(1174.7, 122);
|
||||
play(740.0, 122);
|
||||
play(987.8, 122);
|
||||
play(740.0, 122);
|
||||
play(1174.7, 122);
|
||||
play(740.0, 122);
|
||||
play(987.8, 122);
|
||||
play(740.0, 122);
|
||||
play(1174.7, 122);
|
||||
play(830.6, 122);
|
||||
play(987.8, 122);
|
||||
play(830.6, 122);
|
||||
play(1174.7, 122);
|
||||
play(830.6, 122);
|
||||
play(987.8, 122);
|
||||
play(830.6, 122);
|
||||
play(1174.7, 122);
|
||||
play(830.6, 122);
|
||||
play(987.8, 122);
|
||||
play(830.6, 122);
|
||||
play(1174.7, 122);
|
||||
play(830.6, 122);
|
||||
play(987.8, 122);
|
||||
play(830.6, 122);
|
||||
play(1568.0, 122);
|
||||
play(987.8, 122);
|
||||
play(1318.5, 122);
|
||||
play(987.8, 122);
|
||||
play(1568.0, 122);
|
||||
play(987.8, 122);
|
||||
play(1318.5, 122);
|
||||
play(987.8, 122);
|
||||
play(1568.0, 122);
|
||||
play(987.8, 122);
|
||||
play(1318.5, 122);
|
||||
play(987.8, 122);
|
||||
play(1568.0, 122);
|
||||
play(987.8, 122);
|
||||
play(1318.5, 122);
|
||||
play(987.8, 122);
|
||||
play(1318.5, 122);
|
||||
play(880.0, 122);
|
||||
play(1108.7, 122);
|
||||
play(880.0, 122);
|
||||
play(1318.5, 122);
|
||||
play(880.0, 122);
|
||||
play(1108.7, 122);
|
||||
play(880.0, 122);
|
||||
play(1318.5, 122);
|
||||
play(880.0, 122);
|
||||
play(1108.7, 122);
|
||||
play(880.0, 122);
|
||||
play(1318.5, 122);
|
||||
play(880.0, 122);
|
||||
play(1108.7, 122);
|
||||
play(1174.7, 122);
|
||||
play(740.0, 122);
|
||||
play(987.8, 122);
|
||||
play(740.0, 122);
|
||||
play(1174.7, 122);
|
||||
play(740.0, 122);
|
||||
play(987.8, 122);
|
||||
play(740.0, 122);
|
||||
play(1174.7, 122);
|
||||
play(740.0, 122);
|
||||
play(987.8, 122);
|
||||
play(740.0, 122);
|
||||
play(1174.7, 122);
|
||||
play(740.0, 122);
|
||||
play(987.8, 122);
|
||||
play(740.0, 122);
|
||||
play(1174.7, 122);
|
||||
play(830.6, 122);
|
||||
play(987.8, 122);
|
||||
play(830.6, 122);
|
||||
play(1174.7, 122);
|
||||
play(830.6, 122);
|
||||
play(987.8, 122);
|
||||
play(830.6, 122);
|
||||
play(1174.7, 122);
|
||||
play(830.6, 122);
|
||||
play(987.8, 122);
|
||||
play(830.6, 122);
|
||||
play(1174.7, 122);
|
||||
play(830.6, 122);
|
||||
play(987.8, 122);
|
||||
play(830.6, 122);
|
||||
play(1568.0, 122);
|
||||
play(987.8, 122);
|
||||
play(1318.5, 122);
|
||||
play(987.8, 122);
|
||||
play(1568.0, 122);
|
||||
play(987.8, 122);
|
||||
play(1318.5, 122);
|
||||
play(987.8, 122);
|
||||
play(1568.0, 122);
|
||||
play(987.8, 122);
|
||||
play(1318.5, 122);
|
||||
play(987.8, 122);
|
||||
play(1568.0, 122);
|
||||
play(987.8, 122);
|
||||
play(1318.5, 122);
|
||||
play(987.8, 122);
|
||||
play(1318.5, 122);
|
||||
play(880.0, 122);
|
||||
play(1108.7, 122);
|
||||
play(880.0, 122);
|
||||
play(1318.5, 122);
|
||||
play(880.0, 122);
|
||||
play(1108.7, 122);
|
||||
play(880.0, 122);
|
||||
play(1318.5, 122);
|
||||
play(880.0, 122);
|
||||
play(1108.7, 122);
|
||||
play(880.0, 122);
|
||||
play(1318.5, 122);
|
||||
play(880.0, 122);
|
||||
play(1108.7, 122);
|
||||
play(1174.7, 122);
|
||||
play(740.0, 122);
|
||||
play(987.8, 122);
|
||||
play(740.0, 122);
|
||||
play(1174.7, 122);
|
||||
play(740.0, 122);
|
||||
play(987.8, 122);
|
||||
play(740.0, 122);
|
||||
play(1174.7, 122);
|
||||
play(740.0, 122);
|
||||
play(987.8, 122);
|
||||
play(740.0, 122);
|
||||
play(1174.7, 122);
|
||||
play(740.0, 122);
|
||||
play(987.8, 122);
|
||||
play(740.0, 122);
|
||||
play(1174.7, 122);
|
||||
play(830.6, 122);
|
||||
play(987.8, 122);
|
||||
play(830.6, 122);
|
||||
play(1174.7, 122);
|
||||
play(830.6, 122);
|
||||
play(987.8, 122);
|
||||
play(830.6, 122);
|
||||
play(1174.7, 122);
|
||||
play(830.6, 122);
|
||||
play(987.8, 122);
|
||||
play(830.6, 122);
|
||||
play(1174.7, 122);
|
||||
play(830.6, 122);
|
||||
play(987.8, 122);
|
||||
play(830.6, 122);
|
||||
play(1568.0, 122);
|
||||
play(987.8, 122);
|
||||
play(1318.5, 122);
|
||||
play(987.8, 122);
|
||||
play(1568.0, 122);
|
||||
play(987.8, 122);
|
||||
play(1318.5, 122);
|
||||
play(987.8, 122);
|
||||
play(1568.0, 122);
|
||||
play(987.8, 122);
|
||||
play(1318.5, 122);
|
||||
play(987.8, 122);
|
||||
play(1568.0, 122);
|
||||
play(987.8, 122);
|
||||
play(1318.5, 122);
|
||||
play(987.8, 122);
|
||||
play(1318.5, 122);
|
||||
play(880.0, 122);
|
||||
play(1108.7, 122);
|
||||
play(880.0, 122);
|
||||
play(1318.5, 122);
|
||||
play(880.0, 122);
|
||||
play(1108.7, 122);
|
||||
play(880.0, 122);
|
||||
play(1318.5, 122);
|
||||
play(880.0, 122);
|
||||
play(1108.7, 122);
|
||||
play(880.0, 122);
|
||||
play(1318.5, 122);
|
||||
play(880.0, 122);
|
||||
play(1108.7, 122);
|
||||
play(1174.7, 122);
|
||||
play(740.0, 122);
|
||||
play(987.8, 122);
|
||||
play(740.0, 122);
|
||||
play(1174.7, 122);
|
||||
play(740.0, 122);
|
||||
play(987.8, 122);
|
||||
play(740.0, 122);
|
||||
play(1174.7, 122);
|
||||
play(740.0, 122);
|
||||
play(987.8, 122);
|
||||
play(740.0, 122);
|
||||
play(1174.7, 122);
|
||||
play(740.0, 122);
|
||||
play(987.8, 122);
|
||||
play(740.0, 122);
|
||||
play(1174.7, 122);
|
||||
play(830.6, 122);
|
||||
play(987.8, 122);
|
||||
play(830.6, 122);
|
||||
play(1174.7, 122);
|
||||
play(830.6, 122);
|
||||
play(987.8, 122);
|
||||
play(830.6, 122);
|
||||
play(1174.7, 122);
|
||||
play(830.6, 122);
|
||||
play(987.8, 122);
|
||||
play(830.6, 122);
|
||||
play(1174.7, 122);
|
||||
play(830.6, 122);
|
||||
play(987.8, 122);
|
||||
play(830.6, 122);
|
||||
play(1568.0, 122);
|
||||
play(987.8, 122);
|
||||
play(1318.5, 122);
|
||||
play(987.8, 122);
|
||||
play(1568.0, 122);
|
||||
play(987.8, 122);
|
||||
play(1318.5, 122);
|
||||
play(987.8, 122);
|
||||
play(1568.0, 122);
|
||||
play(987.8, 122);
|
||||
play(1318.5, 122);
|
||||
play(987.8, 122);
|
||||
play(1568.0, 122);
|
||||
play(987.8, 122);
|
||||
play(1318.5, 122);
|
||||
play(987.8, 122);
|
||||
play(1318.5, 122);
|
||||
play(880.0, 122);
|
||||
play(1108.7, 122);
|
||||
play(880.0, 122);
|
||||
play(1318.5, 122);
|
||||
play(880.0, 122);
|
||||
play(1108.7, 122);
|
||||
play(880.0, 122);
|
||||
play(1318.5, 122);
|
||||
play(880.0, 122);
|
||||
play(1108.7, 122);
|
||||
play(880.0, 122);
|
||||
play(1318.5, 122);
|
||||
play(880.0, 122);
|
||||
play(1108.7, 122);
|
||||
play(1174.7, 122);
|
||||
play(740.0, 122);
|
||||
play(987.8, 122);
|
||||
play(740.0, 122);
|
||||
play(1174.7, 122);
|
||||
play(740.0, 122);
|
||||
play(987.8, 122);
|
||||
play(740.0, 122);
|
||||
play(1174.7, 122);
|
||||
play(740.0, 122);
|
||||
play(987.8, 122);
|
||||
play(740.0, 122);
|
||||
play(1174.7, 122);
|
||||
play(740.0, 122);
|
||||
play(987.8, 122);
|
||||
play(740.0, 122);
|
||||
play(1174.7, 122);
|
||||
play(830.6, 122);
|
||||
play(987.8, 122);
|
||||
play(830.6, 122);
|
||||
play(1174.7, 122);
|
||||
play(830.6, 122);
|
||||
play(987.8, 122);
|
||||
play(830.6, 122);
|
||||
play(1174.7, 122);
|
||||
play(830.6, 122);
|
||||
play(987.8, 122);
|
||||
play(830.6, 122);
|
||||
play(1174.7, 122);
|
||||
play(830.6, 122);
|
||||
play(987.8, 122);
|
||||
play(830.6, 122);
|
||||
play(1568.0, 122);
|
||||
play(987.8, 122);
|
||||
play(1318.5, 122);
|
||||
play(987.8, 122);
|
||||
play(1568.0, 122);
|
||||
play(987.8, 122);
|
||||
play(1318.5, 122);
|
||||
play(987.8, 122);
|
||||
play(1568.0, 122);
|
||||
play(987.8, 122);
|
||||
play(1318.5, 122);
|
||||
play(987.8, 122);
|
||||
play(1568.0, 122);
|
||||
play(987.8, 122);
|
||||
play(1318.5, 122);
|
||||
play(987.8, 122);
|
||||
play(1318.5, 122);
|
||||
play(880.0, 122);
|
||||
play(1108.7, 122);
|
||||
play(880.0, 122);
|
||||
play(1318.5, 122);
|
||||
play(880.0, 122);
|
||||
play(1108.7, 122);
|
||||
play(880.0, 122);
|
||||
play(1318.5, 122);
|
||||
play(880.0, 122);
|
||||
play(1108.7, 122);
|
||||
play(880.0, 122);
|
||||
play(1318.5, 122);
|
||||
play(880.0, 122);
|
||||
play(1108.7, 122);
|
||||
play(587.3, 122);
|
||||
play(370.0, 122);
|
||||
play(493.9, 122);
|
||||
play(370.0, 122);
|
||||
play(587.3, 122);
|
||||
play(370.0, 122);
|
||||
play(493.9, 122);
|
||||
play(370.0, 122);
|
||||
play(587.3, 122);
|
||||
play(370.0, 122);
|
||||
play(493.9, 122);
|
||||
play(370.0, 122);
|
||||
play(587.3, 122);
|
||||
play(370.0, 122);
|
||||
play(493.9, 122);
|
||||
play(370.0, 122);
|
||||
play(587.3, 122);
|
||||
play(415.3, 122);
|
||||
play(493.9, 122);
|
||||
play(415.3, 122);
|
||||
play(587.3, 122);
|
||||
play(415.3, 122);
|
||||
play(493.9, 122);
|
||||
play(415.3, 122);
|
||||
play(587.3, 122);
|
||||
play(415.3, 122);
|
||||
play(493.9, 122);
|
||||
play(415.3, 122);
|
||||
play(587.3, 122);
|
||||
play(415.3, 122);
|
||||
play(493.9, 122);
|
||||
play(415.3, 122);
|
||||
play(784.0, 122);
|
||||
play(493.9, 122);
|
||||
play(659.3, 122);
|
||||
play(493.9, 122);
|
||||
play(784.0, 122);
|
||||
play(493.9, 122);
|
||||
play(659.3, 122);
|
||||
play(493.9, 122);
|
||||
play(784.0, 122);
|
||||
play(493.9, 122);
|
||||
play(659.3, 122);
|
||||
play(493.9, 122);
|
||||
play(784.0, 122);
|
||||
play(493.9, 122);
|
||||
play(659.3, 122);
|
||||
play(493.9, 122);
|
||||
play(659.3, 122);
|
||||
play(440.0, 122);
|
||||
play(554.4, 122);
|
||||
play(440.0, 122);
|
||||
play(659.3, 122);
|
||||
play(440.0, 122);
|
||||
play(554.4, 122);
|
||||
play(440.0, 122);
|
||||
play(659.3, 122);
|
||||
play(440.0, 122);
|
||||
play(554.4, 122);
|
||||
play(440.0, 122);
|
||||
play(659.3, 122);
|
||||
play(440.0, 122);
|
||||
play(554.4, 122);
|
||||
play(587.3, 122);
|
||||
play(370.0, 122);
|
||||
play(493.9, 122);
|
||||
play(370.0, 122);
|
||||
play(587.3, 122);
|
||||
play(370.0, 122);
|
||||
play(493.9, 122);
|
||||
play(370.0, 122);
|
||||
play(587.3, 122);
|
||||
play(370.0, 122);
|
||||
play(493.9, 122);
|
||||
play(370.0, 122);
|
||||
play(587.3, 122);
|
||||
play(370.0, 122);
|
||||
play(493.9, 122);
|
||||
play(370.0, 122);
|
||||
play(587.3, 122);
|
||||
play(415.3, 122);
|
||||
play(493.9, 122);
|
||||
play(415.3, 122);
|
||||
play(587.3, 122);
|
||||
play(415.3, 122);
|
||||
play(493.9, 122);
|
||||
play(415.3, 122);
|
||||
play(587.3, 122);
|
||||
play(415.3, 122);
|
||||
play(493.9, 122);
|
||||
play(415.3, 122);
|
||||
play(587.3, 122);
|
||||
play(415.3, 122);
|
||||
play(493.9, 122);
|
||||
play(415.3, 122);
|
||||
play(784.0, 122);
|
||||
play(493.9, 122);
|
||||
play(659.3, 122);
|
||||
play(493.9, 122);
|
||||
play(784.0, 122);
|
||||
play(493.9, 122);
|
||||
play(659.3, 122);
|
||||
play(493.9, 122);
|
||||
play(784.0, 122);
|
||||
play(493.9, 122);
|
||||
play(659.3, 122);
|
||||
play(493.9, 122);
|
||||
play(784.0, 122);
|
||||
play(493.9, 122);
|
||||
play(659.3, 122);
|
||||
play(493.9, 122);
|
||||
play(659.3, 122);
|
||||
play(440.0, 122);
|
||||
play(554.4, 122);
|
||||
play(440.0, 122);
|
||||
play(659.3, 122);
|
||||
play(440.0, 122);
|
||||
play(554.4, 122);
|
||||
play(440.0, 122);
|
||||
play(659.3, 122);
|
||||
play(440.0, 122);
|
||||
play(554.4, 122);
|
||||
play(440.0, 122);
|
||||
play(659.3, 122);
|
||||
play(440.0, 122);
|
||||
play(554.4, 122);
|
||||
play(1174.7, 122);
|
||||
play(740.0, 122);
|
||||
play(987.8, 122);
|
||||
play(740.0, 122);
|
||||
play(1174.7, 122);
|
||||
play(740.0, 122);
|
||||
play(987.8, 122);
|
||||
play(740.0, 122);
|
||||
play(1174.7, 122);
|
||||
play(740.0, 122);
|
||||
play(987.8, 122);
|
||||
play(740.0, 122);
|
||||
play(1174.7, 122);
|
||||
play(740.0, 122);
|
||||
play(987.8, 122);
|
||||
play(740.0, 122);
|
||||
play(1174.7, 122);
|
||||
play(830.6, 122);
|
||||
play(987.8, 122);
|
||||
play(830.6, 122);
|
||||
play(1174.7, 122);
|
||||
play(830.6, 122);
|
||||
play(987.8, 122);
|
||||
play(830.6, 122);
|
||||
play(1174.7, 122);
|
||||
play(830.6, 122);
|
||||
play(987.8, 122);
|
||||
play(830.6, 122);
|
||||
play(1174.7, 122);
|
||||
play(830.6, 122);
|
||||
play(987.8, 122);
|
||||
play(830.6, 122);
|
||||
play(1568.0, 122);
|
||||
play(987.8, 122);
|
||||
play(1318.5, 122);
|
||||
play(987.8, 122);
|
||||
play(1568.0, 122);
|
||||
play(987.8, 122);
|
||||
play(1318.5, 122);
|
||||
play(987.8, 122);
|
||||
play(1568.0, 122);
|
||||
play(987.8, 122);
|
||||
play(1318.5, 122);
|
||||
play(987.8, 122);
|
||||
play(1568.0, 122);
|
||||
play(987.8, 122);
|
||||
play(1318.5, 122);
|
||||
play(987.8, 122);
|
||||
play(1318.5, 122);
|
||||
play(880.0, 122);
|
||||
play(1108.7, 122);
|
||||
play(880.0, 122);
|
||||
play(1318.5, 122);
|
||||
play(880.0, 122);
|
||||
play(1108.7, 122);
|
||||
play(880.0, 122);
|
||||
play(1318.5, 122);
|
||||
play(880.0, 122);
|
||||
play(1108.7, 122);
|
||||
play(880.0, 122);
|
||||
play(1318.5, 122);
|
||||
play(880.0, 122);
|
||||
play(1108.7, 122);
|
||||
play(1174.7, 122);
|
||||
play(740.0, 122);
|
||||
play(987.8, 122);
|
||||
play(740.0, 122);
|
||||
play(1174.7, 122);
|
||||
play(740.0, 122);
|
||||
play(987.8, 122);
|
||||
play(740.0, 122);
|
||||
play(1174.7, 122);
|
||||
play(740.0, 122);
|
||||
play(987.8, 122);
|
||||
play(740.0, 122);
|
||||
play(1174.7, 122);
|
||||
play(740.0, 122);
|
||||
play(987.8, 122);
|
||||
play(740.0, 122);
|
||||
play(1174.7, 122);
|
||||
play(830.6, 122);
|
||||
play(987.8, 122);
|
||||
play(830.6, 122);
|
||||
play(1174.7, 122);
|
||||
play(830.6, 122);
|
||||
play(987.8, 122);
|
||||
play(830.6, 122);
|
||||
play(1174.7, 122);
|
||||
play(830.6, 122);
|
||||
play(987.8, 122);
|
||||
play(830.6, 122);
|
||||
play(1174.7, 122);
|
||||
play(830.6, 122);
|
||||
play(987.8, 122);
|
||||
play(830.6, 122);
|
||||
play(1568.0, 122);
|
||||
play(987.8, 122);
|
||||
play(1318.5, 122);
|
||||
play(987.8, 122);
|
||||
play(1568.0, 122);
|
||||
play(987.8, 122);
|
||||
play(1318.5, 122);
|
||||
play(987.8, 122);
|
||||
play(1568.0, 122);
|
||||
play(987.8, 122);
|
||||
play(1318.5, 122);
|
||||
play(987.8, 122);
|
||||
play(1568.0, 122);
|
||||
play(987.8, 122);
|
||||
play(1318.5, 122);
|
||||
play(987.8, 122);
|
||||
play(1318.5, 122);
|
||||
play(880.0, 122);
|
||||
play(1108.7, 122);
|
||||
play(880.0, 122);
|
||||
play(1318.5, 122);
|
||||
play(880.0, 122);
|
||||
play(1108.7, 122);
|
||||
play(880.0, 122);
|
||||
play(1318.5, 122);
|
||||
play(880.0, 122);
|
||||
play(1108.7, 122);
|
||||
play(880.0, 122);
|
||||
play(1318.5, 122);
|
||||
play(880.0, 122);
|
||||
play(1108.7, 122);
|
||||
play(880.0, 122);
|
||||
off();
|
||||
}
|
89
src/device/sound/PCSPK.h
Executable file
89
src/device/sound/PCSPK.h
Executable file
@ -0,0 +1,89 @@
|
||||
/*****************************************************************************
|
||||
* *
|
||||
* P C S P K *
|
||||
* *
|
||||
*---------------------------------------------------------------------------*
|
||||
* Beschreibung: Mit Hilfe dieser Klasse kann man Toene auf dem *
|
||||
* PC-Lautsprecher ausgeben. *
|
||||
* *
|
||||
* Achtung: Qemu muss mit dem Parameter -soundhw pcspk aufgerufen *
|
||||
* werden. Ansonsten kann man nichts hoeren. *
|
||||
* *
|
||||
* Autor: Michael Schoettner, HHU, 22.9.2016 *
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef PCSPK_include__
|
||||
#define PCSPK_include__
|
||||
|
||||
#include "device/port/IOport.h"
|
||||
|
||||
// Note, Frequenz
|
||||
constexpr const float C0 = 130.81;
|
||||
constexpr const float C0X = 138.59;
|
||||
constexpr const float D0 = 146.83;
|
||||
constexpr const float D0X = 155.56;
|
||||
constexpr const float E0 = 164.81;
|
||||
constexpr const float F0 = 174.61;
|
||||
constexpr const float F0X = 185.00;
|
||||
constexpr const float G0 = 196.00;
|
||||
constexpr const float G0X = 207.65;
|
||||
constexpr const float A0 = 220.00;
|
||||
constexpr const float A0X = 233.08;
|
||||
constexpr const float B0 = 246.94;
|
||||
|
||||
constexpr const float C1 = 261.63;
|
||||
constexpr const float C1X = 277.18;
|
||||
constexpr const float D1 = 293.66;
|
||||
constexpr const float D1X = 311.13;
|
||||
constexpr const float E1 = 329.63;
|
||||
constexpr const float F1 = 349.23;
|
||||
constexpr const float F1X = 369.99;
|
||||
constexpr const float G1 = 391.00;
|
||||
constexpr const float G1X = 415.30;
|
||||
constexpr const float A1 = 440.00;
|
||||
constexpr const float A1X = 466.16;
|
||||
constexpr const float B1 = 493.88;
|
||||
|
||||
constexpr const float C2 = 523.25;
|
||||
constexpr const float C2X = 554.37;
|
||||
constexpr const float D2 = 587.33;
|
||||
constexpr const float D2X = 622.25;
|
||||
constexpr const float E2 = 659.26;
|
||||
constexpr const float F2 = 698.46;
|
||||
constexpr const float F2X = 739.99;
|
||||
constexpr const float G2 = 783.99;
|
||||
constexpr const float G2X = 830.61;
|
||||
constexpr const float A2 = 880.00;
|
||||
constexpr const float A2X = 923.33;
|
||||
constexpr const float B2 = 987.77;
|
||||
constexpr const float C3 = 1046.50;
|
||||
|
||||
class PCSPK {
|
||||
private:
|
||||
static const IOport control; // Steuerregister (write only)
|
||||
static const IOport data2; // Zaehler-2 Datenregister
|
||||
static const IOport ppi; // Status-Register des PPI
|
||||
|
||||
// Verzoegerung um X ms (in 1ms Schritten; Min. 1ms)
|
||||
static inline void delay(int time);
|
||||
|
||||
public:
|
||||
PCSPK(const PCSPK& copy) = delete; // Verhindere Kopieren
|
||||
|
||||
// Konstruktor. Initialisieren der Ports.
|
||||
PCSPK() = default;
|
||||
|
||||
// Can't make singleton because atexit
|
||||
|
||||
// Demo Sounds
|
||||
static void tetris();
|
||||
static void aerodynamic();
|
||||
|
||||
// Ton abspielen
|
||||
static void play(float f, int len);
|
||||
|
||||
// Lautsprecher ausschalten
|
||||
static void off();
|
||||
};
|
||||
|
||||
#endif
|
88
src/device/time/PIT.cc
Executable file
88
src/device/time/PIT.cc
Executable file
@ -0,0 +1,88 @@
|
||||
/*****************************************************************************
|
||||
* *
|
||||
* P I T *
|
||||
* *
|
||||
*---------------------------------------------------------------------------*
|
||||
* Beschreibung: Programmable Interval Timer. *
|
||||
* *
|
||||
* Autor: Michael Schoettner, 3.7.2022 *
|
||||
*****************************************************************************/
|
||||
|
||||
#include "PIT.h"
|
||||
#include "kernel/system/Globals.h"
|
||||
|
||||
const IOport PIT::control(0x43);
|
||||
const IOport PIT::data0(0x40);
|
||||
|
||||
/*****************************************************************************
|
||||
* Methode: PIT::interval *
|
||||
*---------------------------------------------------------------------------*
|
||||
* Beschreibung: Zeitinervall programmieren. *
|
||||
* *
|
||||
* Parameter: *
|
||||
* us: Zeitintervall in Mikrosekunden, nachdem periodisch ein *
|
||||
* Interrupt erzeugt werden soll. *
|
||||
*****************************************************************************/
|
||||
void PIT::interval(int us) {
|
||||
|
||||
/* hier muss Code eingefuegt werden */
|
||||
|
||||
control.outb(0x36); // Zähler 0 Mode 3
|
||||
|
||||
unsigned int cntStart = static_cast<unsigned int>((1193180.0 / 1000000.0) * us); // 1.19Mhz PIT
|
||||
|
||||
data0.outb(cntStart & 0xFF); // Zaehler-0 laden (Lobyte)
|
||||
data0.outb(cntStart >> 8); // Zaehler-0 laden (Hibyte)
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* Methode: PIT::plugin *
|
||||
*---------------------------------------------------------------------------*
|
||||
* Beschreibung: Unterbrechungen fuer den Zeitgeber erlauben. Ab sofort *
|
||||
* wird bei Ablauf des definierten Zeitintervalls die *
|
||||
* Methode 'trigger' aufgerufen. *
|
||||
*****************************************************************************/
|
||||
void PIT::plugin() {
|
||||
|
||||
/* hier muss Code eingefuegt werden */
|
||||
|
||||
intdis.assign(IntDispatcher::timer, *this);
|
||||
PIC::allow(PIC::timer);
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* Methode: PIT::trigger *
|
||||
*---------------------------------------------------------------------------*
|
||||
* Beschreibung: ISR fuer den Zeitgeber. Wird aufgerufen, wenn der *
|
||||
* Zeitgeber eine Unterbrechung ausloest. Anzeige der Uhr *
|
||||
* aktualisieren und Thread wechseln durch Setzen der *
|
||||
* Variable 'forceSwitch', wird in 'int_disp' behandelt. *
|
||||
*****************************************************************************/
|
||||
void PIT::trigger() {
|
||||
|
||||
/* hier muss Code eingefuegt werden */
|
||||
|
||||
// log << TRACE << "Incrementing systime" << endl;
|
||||
|
||||
// alle 10ms, Systemzeit weitersetzen
|
||||
systime++;
|
||||
|
||||
// Bei jedem Tick einen Threadwechsel ausloesen.
|
||||
// Aber nur wenn der Scheduler bereits fertig intialisiert wurde
|
||||
// und ein weiterer Thread rechnen moechte
|
||||
|
||||
/* hier muss Code eingefuegt werden */
|
||||
|
||||
// Indicator
|
||||
if (systime - last_indicator_refresh >= 10) {
|
||||
indicator_pos = (indicator_pos + 1) % 4;
|
||||
CGA::show(79, 0, indicator[indicator_pos]);
|
||||
last_indicator_refresh = systime;
|
||||
}
|
||||
|
||||
// Preemption
|
||||
if (scheduler.preemption_enabled()) {
|
||||
// log << TRACE << "Preemption" << endl;
|
||||
scheduler.preempt();
|
||||
}
|
||||
}
|
54
src/device/time/PIT.h
Executable file
54
src/device/time/PIT.h
Executable file
@ -0,0 +1,54 @@
|
||||
/*****************************************************************************
|
||||
* *
|
||||
* P I T *
|
||||
* *
|
||||
*---------------------------------------------------------------------------*
|
||||
* Beschreibung: Programmable Interval Timer. *
|
||||
* *
|
||||
* Autor: Michael Schoettner, 23.8.2016 *
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef PIT_include__
|
||||
#define PIT_include__
|
||||
|
||||
#include "kernel/interrupt/ISR.h"
|
||||
#include "device/port/IOport.h"
|
||||
#include "lib/util/Array.h"
|
||||
|
||||
class PIT : public ISR {
|
||||
private:
|
||||
const static IOport control;
|
||||
const static IOport data0;
|
||||
|
||||
enum { time_base = 838 }; /* ns */
|
||||
int timer_interval;
|
||||
|
||||
const bse::array<char, 4> indicator{'|', '/', '-', '\\'};
|
||||
unsigned int indicator_pos = 0;
|
||||
unsigned long last_indicator_refresh = 0;
|
||||
|
||||
public:
|
||||
PIT(const PIT& copy) = delete; // Verhindere Kopieren
|
||||
|
||||
// ~PIT() override = default;
|
||||
|
||||
// Zeitgeber initialisieren.
|
||||
explicit PIT(int us) {
|
||||
PIT::interval(us);
|
||||
}
|
||||
|
||||
// Konfiguriertes Zeitintervall auslesen.
|
||||
int interval() const { return timer_interval; }
|
||||
|
||||
// Zeitintervall in Mikrosekunden, nachdem periodisch ein Interrupt
|
||||
//erzeugt werden soll.
|
||||
static void interval(int us);
|
||||
|
||||
// Aktivierung der Unterbrechungen fuer den Zeitgeber
|
||||
void plugin();
|
||||
|
||||
// Unterbrechnungsroutine des Zeitgebers.
|
||||
void trigger() override;
|
||||
};
|
||||
|
||||
#endif
|
40
src/kernel/demo/ArrayDemo.cc
Normal file
40
src/kernel/demo/ArrayDemo.cc
Normal file
@ -0,0 +1,40 @@
|
||||
#include "ArrayDemo.h"
|
||||
|
||||
void ArrayDemo::run() {
|
||||
bse::array<int, 10> arr1 {};
|
||||
bse::array<int, 10> arr2 {};
|
||||
|
||||
kout.lock();
|
||||
kout.clear();
|
||||
|
||||
kout << "Adding..." << endl;
|
||||
for (int i = 0; i < 10; ++i) {
|
||||
arr1[i] = i;
|
||||
}
|
||||
|
||||
kout << "Iterator printing arr1:" << endl;
|
||||
for (int i : arr1) {
|
||||
kout << i << " ";
|
||||
}
|
||||
kout << endl;
|
||||
|
||||
kout << "Swapping arr1 and arr2..." << endl;
|
||||
arr1.swap(arr2);
|
||||
|
||||
kout << "Iterator printing arr1:" << endl;
|
||||
for (int i : arr1) {
|
||||
kout << i << " ";
|
||||
}
|
||||
kout << endl;
|
||||
|
||||
kout << "Iterator printing arr2:" << endl;
|
||||
for (int i : arr2) {
|
||||
kout << i << " ";
|
||||
}
|
||||
kout << endl;
|
||||
|
||||
// arr1.swap(arr3); // Not possible as type/size has to match
|
||||
|
||||
kout.unlock();
|
||||
scheduler.exit();
|
||||
}
|
16
src/kernel/demo/ArrayDemo.h
Normal file
16
src/kernel/demo/ArrayDemo.h
Normal file
@ -0,0 +1,16 @@
|
||||
#ifndef ArrayDemo_include__
|
||||
#define ArrayDemo_include__
|
||||
|
||||
#include "kernel/system/Globals.h"
|
||||
#include "lib/util/Array.h"
|
||||
|
||||
class ArrayDemo : public Thread {
|
||||
public:
|
||||
ArrayDemo(const ArrayDemo& copy) = delete;
|
||||
|
||||
ArrayDemo() : Thread("ArrayDemo") {}
|
||||
|
||||
void run() override;
|
||||
};
|
||||
|
||||
#endif
|
78
src/kernel/demo/HeapDemo.cc
Executable file
78
src/kernel/demo/HeapDemo.cc
Executable file
@ -0,0 +1,78 @@
|
||||
/*****************************************************************************
|
||||
* *
|
||||
* H E A P D E M O *
|
||||
* *
|
||||
*---------------------------------------------------------------------------*
|
||||
* Beschreibung: Demonstration der dynamischen Speicherverwaltung. *
|
||||
* *
|
||||
* Autor: Michael Schoettner, HHU, 27.12.2016 *
|
||||
*****************************************************************************/
|
||||
|
||||
#include "HeapDemo.h"
|
||||
|
||||
void HeapDemo::run() {
|
||||
kout.lock();
|
||||
kout.clear();
|
||||
kout << "HEAP_DEMO ===================================================================" << endl;
|
||||
|
||||
/* hier muss Code eingefuegt werden */
|
||||
|
||||
allocator.dump_free_memory();
|
||||
|
||||
// Rounding to word border
|
||||
kout << "ROUNDING ====================================================================" << endl;
|
||||
void* alloc = allocator.alloc(1); // 1 Byte
|
||||
allocator.dump_free_memory();
|
||||
allocator.free(alloc);
|
||||
allocator.dump_free_memory();
|
||||
|
||||
// Some objects and forward/backward merging
|
||||
kout << "SOME OBJECTS ================================================================" << endl;
|
||||
MyObj* a = new MyObj(5);
|
||||
allocator.dump_free_memory();
|
||||
MyObj* b = new MyObj(10);
|
||||
allocator.dump_free_memory();
|
||||
MyObj* c = new MyObj(15);
|
||||
allocator.dump_free_memory();
|
||||
delete b; // No merge
|
||||
allocator.dump_free_memory();
|
||||
delete a; // Merge forward BUG: Bluescreen
|
||||
allocator.dump_free_memory();
|
||||
delete c;
|
||||
allocator.dump_free_memory();
|
||||
|
||||
// Allocate too whole heap
|
||||
// void* ptr = allocator.alloc(1024 * 1024 - 24);
|
||||
// allocator.dump_free_memory();
|
||||
// allocator.free(ptr);
|
||||
// allocator.dump_free_memory();
|
||||
|
||||
// Allocate too much
|
||||
kout << "TOO MUCH ====================================================================" << endl;
|
||||
allocator.alloc(1024 * 1024); // should fail as only 1024 * 1024 - Headersize bytes are available
|
||||
allocator.dump_free_memory();
|
||||
|
||||
// A lot of allocations
|
||||
// MyObj* objs[1024];
|
||||
// for (unsigned int i = 0; i < 1024; ++i) {
|
||||
// objs[i] = new MyObj(5);
|
||||
// }
|
||||
// allocator.dump_free_memory();
|
||||
// waitForReturn();
|
||||
// for (unsigned int i = 0; i < 1024; ++i) {
|
||||
// delete objs[i];
|
||||
// }
|
||||
// allocator.dump_free_memory();
|
||||
|
||||
// Array allocation
|
||||
kout << "ARRAY =======================================================================" << endl;
|
||||
MyObj* objs = new MyObj[1024];
|
||||
allocator.dump_free_memory();
|
||||
delete[] objs;
|
||||
allocator.dump_free_memory();
|
||||
|
||||
kout << "HEAP_DEMO END ===============================================================" << endl;
|
||||
|
||||
kout.unlock();
|
||||
scheduler.exit();
|
||||
}
|
32
src/kernel/demo/HeapDemo.h
Executable file
32
src/kernel/demo/HeapDemo.h
Executable file
@ -0,0 +1,32 @@
|
||||
/*****************************************************************************
|
||||
* *
|
||||
* H E A P D E M O *
|
||||
* *
|
||||
*---------------------------------------------------------------------------*
|
||||
* Beschreibung: Demonstration der dynamischen Speicherverwaltung. *
|
||||
* *
|
||||
* Autor: Michael Schoettner, HHU, 25.9.2016 *
|
||||
*****************************************************************************/
|
||||
#ifndef HeapDemo_include__
|
||||
#define HeapDemo_include__
|
||||
|
||||
#include "kernel/system/Globals.h"
|
||||
#include "kernel/process/Thread.h"
|
||||
|
||||
class MyObj {
|
||||
public:
|
||||
constexpr MyObj() : value(5) {};
|
||||
constexpr MyObj(const unsigned int val) : value(val) {};
|
||||
const unsigned int value;
|
||||
};
|
||||
|
||||
class HeapDemo : public Thread {
|
||||
public:
|
||||
HeapDemo(const HeapDemo& copy) = delete;
|
||||
|
||||
HeapDemo() : Thread("HeapDemo") {}
|
||||
|
||||
void run() override;
|
||||
};
|
||||
|
||||
#endif
|
34
src/kernel/demo/KeyboardDemo.cc
Executable file
34
src/kernel/demo/KeyboardDemo.cc
Executable file
@ -0,0 +1,34 @@
|
||||
/*****************************************************************************
|
||||
* *
|
||||
* K E Y B O A R D D E M O *
|
||||
* *
|
||||
*---------------------------------------------------------------------------*
|
||||
* Beschreibung: Testausgaben für den CGA-Treiber. *
|
||||
* *
|
||||
* Autor: Michael Schoettner, HHU, 26.10.2018 *
|
||||
*****************************************************************************/
|
||||
|
||||
#include "KeyboardDemo.h"
|
||||
|
||||
void KeyboardDemo::run() {
|
||||
|
||||
/* Hier muess Code eingefuegt werden */
|
||||
|
||||
kout << "Keyboard Demo: " << endl;
|
||||
|
||||
kout.lock();
|
||||
kout.clear();
|
||||
kout << "Info: Die Keyboard Demo sperrt den Output Stream:\n"
|
||||
<< " Wenn die Preemption Demo laeuft wird diese also erst\n"
|
||||
<< " fortfahren wenn die Keyboard Demo wieder beendet ist." << endl;
|
||||
kout << "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nInput: ";
|
||||
kout.flush();
|
||||
|
||||
while (running) {
|
||||
kout << listener.waitForKeyEvent();
|
||||
kout.flush();
|
||||
}
|
||||
|
||||
kout.unlock();
|
||||
scheduler.exit();
|
||||
}
|
44
src/kernel/demo/KeyboardDemo.h
Executable file
44
src/kernel/demo/KeyboardDemo.h
Executable file
@ -0,0 +1,44 @@
|
||||
/*****************************************************************************
|
||||
* *
|
||||
* K E Y B O A R D D E M O *
|
||||
* *
|
||||
*---------------------------------------------------------------------------*
|
||||
* Beschreibung: Testausgaben für den CGA-Treiber. *
|
||||
* *
|
||||
* Autor: Michael Schoettner, HHU, 26.10.2018 *
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef KeyboardDemo_include__
|
||||
#define KeyboardDemo_include__
|
||||
|
||||
#include "kernel/system/Globals.h"
|
||||
#include "kernel/process/Thread.h"
|
||||
#include "kernel/event/KeyEventListener.h"
|
||||
|
||||
class KeyboardDemo : public Thread {
|
||||
private:
|
||||
KeyEventListener listener;
|
||||
|
||||
public:
|
||||
KeyboardDemo(const KeyboardDemo& copy) = delete;
|
||||
|
||||
KeyboardDemo() : Thread("KeyboardDemo"), listener(tid) {
|
||||
kevman.subscribe(listener);
|
||||
}
|
||||
|
||||
// Base class destructor will be called automatically
|
||||
~KeyboardDemo() override {
|
||||
if (running) {
|
||||
// NOTE: If the thread was exited nicely it can unlock before destructor,
|
||||
// but on forced kill kout has to be unlocked in the destructor.
|
||||
// This is bad since it could release the lock although some other
|
||||
// thread set it (so use nice_kill)
|
||||
kout.unlock();
|
||||
}
|
||||
kevman.unsubscribe(listener);
|
||||
}
|
||||
|
||||
void run() override;
|
||||
};
|
||||
|
||||
#endif
|
90
src/kernel/demo/MainMenu.cc
Normal file
90
src/kernel/demo/MainMenu.cc
Normal file
@ -0,0 +1,90 @@
|
||||
#include "MainMenu.h"
|
||||
#include "ArrayDemo.h"
|
||||
#include "HeapDemo.h"
|
||||
#include "KeyboardDemo.h"
|
||||
#include "PagingDemo.h"
|
||||
#include "PCSPKdemo.h"
|
||||
#include "PreemptiveThreadDemo.h"
|
||||
#include "SmartPointerDemo.h"
|
||||
#include "StringDemo.h"
|
||||
#include "TextDemo.h"
|
||||
#include "VBEdemo.h"
|
||||
#include "VectorDemo.h"
|
||||
|
||||
void print_demo_menu() {
|
||||
kout.lock();
|
||||
kout.clear();
|
||||
kout << "Demo Menu, press number to start, k/K to kill:\n"
|
||||
<< "1 - Text Demo\n"
|
||||
<< "2 - PCSPK Demo\n"
|
||||
<< "3 - Keyboard Demo\n"
|
||||
<< "4 - Heap Demo\n"
|
||||
<< "5 - VBE Demo\n"
|
||||
<< "6 - Paging Demo\n"
|
||||
<< "7 - Preemption Demo\n"
|
||||
<< "Extra demos:\n"
|
||||
<< "8 - bse::vector demo\n"
|
||||
<< "9 - bse::array demo\n"
|
||||
<< "0 - bse::unique_ptr demo\n"
|
||||
<< "! - bse::string demo\n"
|
||||
<< endl;
|
||||
kout.unlock();
|
||||
}
|
||||
|
||||
void MainMenu::run() {
|
||||
print_demo_menu();
|
||||
|
||||
char input = '\0';
|
||||
unsigned int running_demo = 0;
|
||||
while (running) {
|
||||
input = listener.waitForKeyEvent();
|
||||
|
||||
if ((input >= '0' && input <= '9') || input == '!') {
|
||||
switch (input) {
|
||||
case '1':
|
||||
running_demo = scheduler.ready<TextDemo>();
|
||||
break;
|
||||
case '2':
|
||||
running_demo = scheduler.ready<PCSPKdemo>(&PCSPK::aerodynamic);
|
||||
break;
|
||||
case '3':
|
||||
running_demo = scheduler.ready<KeyboardDemo>();
|
||||
break;
|
||||
case '4':
|
||||
running_demo = scheduler.ready<HeapDemo>();
|
||||
break;
|
||||
case '5':
|
||||
running_demo = scheduler.ready<VBEdemo>();
|
||||
break;
|
||||
case '6':
|
||||
running_demo = scheduler.ready<PagingDemo>();
|
||||
break;
|
||||
case '7':
|
||||
running_demo = scheduler.ready<PreemptiveThreadDemo>(3);
|
||||
break;
|
||||
|
||||
case '8':
|
||||
running_demo = scheduler.ready<VectorDemo>();
|
||||
break;
|
||||
case '9':
|
||||
running_demo = scheduler.ready<ArrayDemo>();
|
||||
break;
|
||||
case '0':
|
||||
running_demo = scheduler.ready<SmartPointerDemo>();
|
||||
break;
|
||||
case '!':
|
||||
running_demo = scheduler.ready<StringDemo>();
|
||||
break;
|
||||
}
|
||||
} else if (input == 'k') {
|
||||
scheduler.nice_kill(running_demo); // NOTE: If thread exits itself this will throw error
|
||||
print_demo_menu();
|
||||
} else if (input == 'K') {
|
||||
scheduler.kill(running_demo);
|
||||
print_demo_menu();
|
||||
}
|
||||
}
|
||||
|
||||
scheduler.exit();
|
||||
// This thread won't be deleted...
|
||||
}
|
26
src/kernel/demo/MainMenu.h
Normal file
26
src/kernel/demo/MainMenu.h
Normal file
@ -0,0 +1,26 @@
|
||||
#ifndef MainMenu_Inlucde_H_
|
||||
#define MainMenu_Inlucde_H_
|
||||
|
||||
#include "kernel/system/Globals.h"
|
||||
#include "kernel/process/Thread.h"
|
||||
#include "kernel/event/KeyEventListener.h"
|
||||
|
||||
class MainMenu : public Thread {
|
||||
private:
|
||||
KeyEventListener listener;
|
||||
|
||||
public:
|
||||
MainMenu(const MainMenu& copy) = delete;
|
||||
|
||||
MainMenu() : Thread("MainMenu"), listener(tid) {
|
||||
kevman.subscribe(listener);
|
||||
}
|
||||
|
||||
~MainMenu() override {
|
||||
kevman.unsubscribe(listener);
|
||||
}
|
||||
|
||||
void run() override;
|
||||
};
|
||||
|
||||
#endif
|
16
src/kernel/demo/PCSPKdemo.cc
Normal file
16
src/kernel/demo/PCSPKdemo.cc
Normal file
@ -0,0 +1,16 @@
|
||||
#include "PCSPKdemo.h"
|
||||
|
||||
void PCSPKdemo::run() {
|
||||
kout.lock();
|
||||
kout.clear();
|
||||
kout << "Playing..." << endl;
|
||||
kout.unlock();
|
||||
|
||||
(*melody)(); // This syntax is confusing as hell
|
||||
|
||||
kout.lock();
|
||||
kout << "Finished" << endl;
|
||||
kout.unlock();
|
||||
|
||||
scheduler.exit();
|
||||
}
|
23
src/kernel/demo/PCSPKdemo.h
Normal file
23
src/kernel/demo/PCSPKdemo.h
Normal file
@ -0,0 +1,23 @@
|
||||
#ifndef PCSPKdemo_INCLUDE_H_
|
||||
#define PCSPKdemo_INCLUDE_H_
|
||||
|
||||
#include "kernel/system/Globals.h"
|
||||
#include "kernel/process/Thread.h"
|
||||
|
||||
class PCSPKdemo : public Thread {
|
||||
private:
|
||||
void (*melody)(); // Allow to pass a melody to play when initializing the demo
|
||||
|
||||
public:
|
||||
PCSPKdemo(const PCSPKdemo& copy) = delete;
|
||||
|
||||
PCSPKdemo(void (*melody)()) : Thread("PCSPKdemo"), melody(melody) {}
|
||||
|
||||
~PCSPKdemo() override {
|
||||
PCSPK::off();
|
||||
}
|
||||
|
||||
void run() override;
|
||||
};
|
||||
|
||||
#endif
|
50
src/kernel/demo/PagingDemo.cc
Normal file
50
src/kernel/demo/PagingDemo.cc
Normal file
@ -0,0 +1,50 @@
|
||||
#include "PagingDemo.h"
|
||||
|
||||
void PagingDemo::writeprotect_page() {
|
||||
kout << "Accessing a writeprotected page triggers bluescreen,\nif you can read this it didn't work" << endl;
|
||||
|
||||
// BlueScreen 1
|
||||
// asm("int $3");
|
||||
|
||||
// BlueScreen 2
|
||||
log.info() << "Allocating page" << endl;
|
||||
unsigned int* page = pg_alloc_page();
|
||||
*page = 42;
|
||||
log.info() << "Writeprotecting page..." << endl;
|
||||
pg_write_protect_page(page);
|
||||
|
||||
log.info() << "Accessing writeprotected page" << endl;
|
||||
*page = 42; // We map logical to physical 1:1 so no need to do any lookup
|
||||
|
||||
// No free because bluescreen
|
||||
}
|
||||
|
||||
void PagingDemo::notpresent_page() {
|
||||
kout << "Produces pagefault, if you can read this it didn't work" << endl;
|
||||
|
||||
log.info() << "Allocating page" << endl;
|
||||
unsigned int* page = pg_alloc_page();
|
||||
*page = 42;
|
||||
|
||||
log.info() << "Marking page notpresent..." << endl;
|
||||
pg_notpresent_page(page);
|
||||
|
||||
log.info() << "Accessing page" << endl;
|
||||
kout << "Page not accessible: " << *page << endl;
|
||||
|
||||
// No free because bluescreen
|
||||
}
|
||||
|
||||
void PagingDemo::run() {
|
||||
kout << "Press w for writeprotect demo, n for notpresent demo" << endl;
|
||||
switch(listener.waitForKeyEvent()) {
|
||||
case 'w':
|
||||
writeprotect_page();
|
||||
break;
|
||||
case 'n':
|
||||
notpresent_page();
|
||||
break;
|
||||
}
|
||||
|
||||
scheduler.exit();
|
||||
}
|
30
src/kernel/demo/PagingDemo.h
Normal file
30
src/kernel/demo/PagingDemo.h
Normal file
@ -0,0 +1,30 @@
|
||||
#ifndef BlueScreenDemo_include__
|
||||
#define BlueScreenDemo_include__
|
||||
|
||||
#include "kernel/system/Globals.h"
|
||||
#include "kernel/process/Thread.h"
|
||||
#include "kernel/event/KeyEventListener.h"
|
||||
|
||||
class PagingDemo: public Thread {
|
||||
private:
|
||||
void writeprotect_page();
|
||||
void free_page();
|
||||
void notpresent_page();
|
||||
|
||||
KeyEventListener listener;
|
||||
|
||||
public:
|
||||
PagingDemo(const PagingDemo& copy) = delete;
|
||||
|
||||
PagingDemo(): Thread("PagingDemo"), listener(tid) {
|
||||
kevman.subscribe(listener);
|
||||
}
|
||||
|
||||
~PagingDemo() override {
|
||||
kevman.unsubscribe(listener);
|
||||
}
|
||||
|
||||
void run() override;
|
||||
};
|
||||
|
||||
#endif
|
34
src/kernel/demo/PreemptiveThreadDemo.cc
Normal file
34
src/kernel/demo/PreemptiveThreadDemo.cc
Normal file
@ -0,0 +1,34 @@
|
||||
#include "PreemptiveThreadDemo.h"
|
||||
|
||||
void PreemptiveLoopThread::run() {
|
||||
int cnt = 0;
|
||||
|
||||
while (running) {
|
||||
// Basic synchronization by semaphore
|
||||
kout.lock();
|
||||
|
||||
// Saving + restoring kout position doesn't help much as preemption still occurs
|
||||
CGA_Stream::setpos(55, id);
|
||||
kout << fillw(3) << id << fillw(0) << ": " << dec << cnt++ << endl;
|
||||
|
||||
kout.unlock();
|
||||
}
|
||||
|
||||
scheduler.exit();
|
||||
}
|
||||
|
||||
void PreemptiveThreadDemo::run() {
|
||||
kout.lock();
|
||||
kout.clear();
|
||||
|
||||
kout << "Preemptive Thread Demo:" << endl;
|
||||
|
||||
kout << "Readying LoopThreads" << endl;
|
||||
for (unsigned int i = 0; i < number_of_threads; ++i) {
|
||||
scheduler.ready<PreemptiveLoopThread>(i);
|
||||
}
|
||||
|
||||
kout << "Exiting main thread" << endl;
|
||||
kout.unlock();
|
||||
scheduler.exit();
|
||||
}
|
35
src/kernel/demo/PreemptiveThreadDemo.h
Normal file
35
src/kernel/demo/PreemptiveThreadDemo.h
Normal file
@ -0,0 +1,35 @@
|
||||
#ifndef preemptive_thread_include__
|
||||
#define preemptive_thread_include__
|
||||
|
||||
#include "kernel/system/Globals.h"
|
||||
#include "kernel/process/Thread.h"
|
||||
#include "lib/async/Semaphore.h"
|
||||
|
||||
class PreemptiveLoopThread : public Thread {
|
||||
private:
|
||||
int id;
|
||||
|
||||
public:
|
||||
PreemptiveLoopThread(const PreemptiveLoopThread& copy) = delete; // Verhindere Kopieren
|
||||
|
||||
// Gibt der Loop einen Stack und eine Id.
|
||||
PreemptiveLoopThread(int i) : Thread("LoopThread"), id(i) {}
|
||||
|
||||
// Zaehlt einen Zaehler hoch und gibt ihn auf dem Bildschirm aus.
|
||||
void run() override;
|
||||
};
|
||||
|
||||
class PreemptiveThreadDemo : public Thread {
|
||||
private:
|
||||
unsigned int number_of_threads;
|
||||
|
||||
public:
|
||||
PreemptiveThreadDemo(const PreemptiveThreadDemo& copy) = delete; // Verhindere Kopieren
|
||||
|
||||
PreemptiveThreadDemo(unsigned int n) : Thread("PreemptiveThreadDemo"), number_of_threads(n) {}
|
||||
|
||||
// Thread-Startmethode
|
||||
void run() override;
|
||||
};
|
||||
|
||||
#endif
|
122
src/kernel/demo/SmartPointerDemo.cc
Normal file
122
src/kernel/demo/SmartPointerDemo.cc
Normal file
@ -0,0 +1,122 @@
|
||||
#include "SmartPointerDemo.h"
|
||||
#include "kernel/process/IdleThread.h"
|
||||
|
||||
void SmartPointerDemo::run() {
|
||||
kout.lock();
|
||||
kout.clear();
|
||||
|
||||
kout << "Output is written to log to be able to trace memory allocations/deallocations" << endl;
|
||||
|
||||
{
|
||||
log.info() << "Allocating new unique_ptr<int>..." << endl;
|
||||
bse::unique_ptr<int> ptr = bse::make_unique<int>(1);
|
||||
log.info() << "Leaving scope..." << endl;
|
||||
}
|
||||
log.info() << "Should be deleted by now..." << endl;
|
||||
|
||||
{
|
||||
log.info() << "Allocating new unique_ptr<int>..." << endl;
|
||||
bse::unique_ptr<int> ptr1 = bse::make_unique<int>(1);
|
||||
bse::unique_ptr<int> ptr2;
|
||||
|
||||
log.info() << "*ptr1 == " << *ptr1 << ", (bool)ptr2 == " << static_cast<bool>(ptr2) << endl;
|
||||
log.info() << "Moving ptr1 => ptr2 (no allocations should happen)..." << endl;
|
||||
ptr2 = std::move(ptr1);
|
||||
log.info() << "(bool)ptr1 == " << static_cast<bool>(ptr1) << ", *ptr2 == " << *ptr2 << endl;
|
||||
|
||||
log.info() << "Leaving scope..." << endl;
|
||||
}
|
||||
log.info() << "Should be deleted by now..." << endl;
|
||||
|
||||
{
|
||||
log.info() << "Allocating (2) new unique_ptr<int>..." << endl;
|
||||
bse::unique_ptr<int> ptr1 = bse::make_unique<int>(1);
|
||||
bse::unique_ptr<int> ptr2 = bse::make_unique<int>(1);
|
||||
|
||||
log.info() << "Moving ptr1 => ptr2 (ptr1 should be freed)..." << endl;
|
||||
ptr2 = std::move(ptr1);
|
||||
|
||||
log.info() << "Leaving scope..." << endl;
|
||||
}
|
||||
log.info() << "Should be deleted by now..." << endl;
|
||||
|
||||
// =====================================================================
|
||||
|
||||
{
|
||||
log.info() << "Allocating new unique_ptr<int[]>..." << endl;
|
||||
bse::unique_ptr<int[]> ptr = bse::make_unique<int[]>(10);
|
||||
ptr[0] = 1;
|
||||
log.info() << "ptr[0] == " << ptr[0] << endl;
|
||||
}
|
||||
log.info() << "Should be deleted by now..." << endl;
|
||||
|
||||
{
|
||||
log.info() << "Allocating new unique_ptr<int[10]>..." << endl;
|
||||
bse::unique_ptr<int[]> ptr1 = bse::make_unique<int[]>(10);
|
||||
bse::unique_ptr<int[]> ptr2;
|
||||
|
||||
log.info() << "Moving ptr1 => ptr2 (no allocations should happen)..." << endl;
|
||||
ptr2 = std::move(ptr1);
|
||||
|
||||
log.info() << "Leaving scope..." << endl;
|
||||
}
|
||||
log.info() << "Should be deleted by now..." << endl;
|
||||
|
||||
{
|
||||
log.info() << "Allocating (2) new unique_ptr<int[10]>..." << endl;
|
||||
bse::unique_ptr<int> ptr1 = bse::make_unique<int>(10);
|
||||
bse::unique_ptr<int> ptr2 = bse::make_unique<int>(10);
|
||||
|
||||
log.info() << "Moving ptr1 => ptr2 (ptr1 should be freed)..." << endl;
|
||||
ptr2 = std::move(ptr1);
|
||||
|
||||
log.info() << "Leaving scope..." << endl;
|
||||
}
|
||||
log.info() << "Should be deleted by now..." << endl;
|
||||
|
||||
// NOTE: This wasn't working because of a missing operator[] delete in the allocator
|
||||
log.info() << "Allocating unique_ptr<int>*..." << endl;
|
||||
bse::unique_ptr<int>* ptrptr = new bse::unique_ptr<int>[10];
|
||||
delete[] ptrptr;
|
||||
log.info() << "Should be deleted by now..." << endl;
|
||||
|
||||
// =====================================================================
|
||||
|
||||
{
|
||||
log.info() << "Stackallocating Array<bse::unique_ptr<int>, 10>..." << endl;
|
||||
bse::array<bse::unique_ptr<int>, 10> arr;
|
||||
log.info() << "Populating slot 0..." << endl;
|
||||
arr[0] = bse::make_unique<int>(1);
|
||||
log.info() << "Moving slot 0 to slot 1..." << endl;
|
||||
arr[1] = std::move(arr[0]);
|
||||
log.info() << "Leaving scope" << endl;
|
||||
}
|
||||
log.info() << "Should be deleted by now..." << endl;
|
||||
|
||||
{
|
||||
log.info() << "Heapallocating Array<bse::unique_ptr<int>, 10>..." << endl;
|
||||
bse::array<bse::unique_ptr<int>, 10>* arr = new bse::array<bse::unique_ptr<int>, 10>;
|
||||
log.info() << "Populating slot 0..." << endl;
|
||||
(*arr)[0] = bse::make_unique<int>(1);
|
||||
log.info() << "Moving slot 0 to slot 1..." << endl;
|
||||
(*arr)[1] = std::move((*arr)[0]);
|
||||
log.info() << "Deleting" << endl;
|
||||
delete arr;
|
||||
log.info() << "Leaving scope" << endl;
|
||||
}
|
||||
log.info() << "Should be deleted by now..." << endl;
|
||||
|
||||
{
|
||||
log.info() << "ArrayList<bse::unique_ptr<int>>..." << endl;
|
||||
bse::vector<bse::unique_ptr<int>> vec;
|
||||
log.info() << "2x insertion" << endl;
|
||||
vec.push_back(bse::make_unique<int>(1));
|
||||
vec.push_back(bse::make_unique<int>(2));
|
||||
|
||||
log.info() << "Leaving scope" << endl;
|
||||
}
|
||||
log.info() << "Should be deleted by now..." << endl;
|
||||
|
||||
kout.unlock();
|
||||
scheduler.exit();
|
||||
}
|
15
src/kernel/demo/SmartPointerDemo.h
Normal file
15
src/kernel/demo/SmartPointerDemo.h
Normal file
@ -0,0 +1,15 @@
|
||||
#ifndef SmartPointerDemo_include__
|
||||
#define SmartPointerDemo_include__
|
||||
|
||||
#include "kernel/system/Globals.h"
|
||||
|
||||
class SmartPointerDemo : public Thread {
|
||||
public:
|
||||
SmartPointerDemo(const SmartPointerDemo& copy) = delete;
|
||||
|
||||
SmartPointerDemo() : Thread("SmartPointerDemo") {}
|
||||
|
||||
void run() override;
|
||||
};
|
||||
|
||||
#endif
|
56
src/kernel/demo/StringDemo.cc
Normal file
56
src/kernel/demo/StringDemo.cc
Normal file
@ -0,0 +1,56 @@
|
||||
#include "StringDemo.h"
|
||||
|
||||
void StringDemo::run() {
|
||||
kout.lock();
|
||||
kout.clear();
|
||||
|
||||
log.info() << "Allocating new string" << endl;
|
||||
bse::string str1 = "This is a dynamically allocated string!";
|
||||
kout << str1 << endl;
|
||||
|
||||
log.info() << "Reassign string" << endl;
|
||||
str1 = "Hello";
|
||||
kout << str1 << " has length " << dec << str1.size() << endl;
|
||||
kout << "Again with strlen: Hello has length " << dec << bse::strlen("Hello") << endl;
|
||||
|
||||
kout << "Adding strings: " << str1 << " + World" << endl;
|
||||
log.info() << "Adding strings" << endl;
|
||||
str1 = str1 + " World";
|
||||
kout << str1 << endl;
|
||||
|
||||
kout << "Hello += World" << endl;
|
||||
log.info() << "Hello += World" << endl;
|
||||
bse::string str3 = "Hello";
|
||||
str3 += " World";
|
||||
kout << str3 << endl;
|
||||
|
||||
kout << "Hello World *= 3" << endl;
|
||||
str3 *= 3;
|
||||
kout << str3 << endl;
|
||||
|
||||
kout << "String iterator!" << endl;
|
||||
for (const char c : str1) {
|
||||
kout << c << " ";
|
||||
}
|
||||
kout << endl;
|
||||
|
||||
log.info() << "Allocating new string" << endl;
|
||||
bse::string str2 = "Hello World";
|
||||
kout << "str1 == str2: " << static_cast<int>(str1 == str2) << endl;
|
||||
kout << "strcmp(Hello, Hello): " << bse::strcmp("Hello", "Hello") << endl;
|
||||
|
||||
log.info() << "Reassign str2" << endl;
|
||||
str2 = "Hello";
|
||||
|
||||
bse::array<char, 5> arr{};
|
||||
arr[0] = 'H';
|
||||
arr[1] = 'e';
|
||||
arr[2] = 'l';
|
||||
arr[3] = 'l';
|
||||
arr[4] = 'o';
|
||||
kout << "bse::array<char, 5> to bse::string: " << static_cast<bse::string>(arr) << ", size: " << (bse::string(arr)).size() << endl;
|
||||
kout << "(bse::string)arr (" << static_cast<bse::string>(arr) << ") == str2 (" << str2 << "): " << static_cast<int>(bse::string(arr) == str2) << endl;
|
||||
|
||||
kout.unlock();
|
||||
scheduler.exit();
|
||||
}
|
15
src/kernel/demo/StringDemo.h
Normal file
15
src/kernel/demo/StringDemo.h
Normal file
@ -0,0 +1,15 @@
|
||||
#ifndef StringDemo_include__
|
||||
#define StringDemo_include__
|
||||
|
||||
#include "kernel/system/Globals.h"
|
||||
|
||||
class StringDemo : public Thread {
|
||||
public:
|
||||
StringDemo(const StringDemo& copy) = delete;
|
||||
|
||||
StringDemo() : Thread("StringDemo") {}
|
||||
|
||||
void run() override;
|
||||
};
|
||||
|
||||
#endif
|
43
src/kernel/demo/TextDemo.cc
Executable file
43
src/kernel/demo/TextDemo.cc
Executable file
@ -0,0 +1,43 @@
|
||||
/*****************************************************************************
|
||||
* *
|
||||
* T E X T D E M O *
|
||||
* *
|
||||
*---------------------------------------------------------------------------*
|
||||
* Beschreibung: Testausgaben für den CGA-Treiber. *
|
||||
* *
|
||||
* Autor: Michael Schoettner, HHU, 26.10.2018 *
|
||||
*****************************************************************************/
|
||||
|
||||
#include "TextDemo.h"
|
||||
|
||||
void TextDemo::run() {
|
||||
|
||||
/* Hier muess Code eingefuegt werden */
|
||||
|
||||
kout.lock();
|
||||
kout.clear();
|
||||
kout << "TextDemo\n"
|
||||
<< endl;
|
||||
|
||||
kout << "Attribut (GREEN on WHITE): "
|
||||
<< bgc(CGA::WHITE) << green << "GREEN on WHITE" << endl
|
||||
<< "Attribut (WHITE on BLACK): "
|
||||
<< bgc(CGA::BLACK) << white << "WHITE on BLACK" << endl;
|
||||
kout << endl;
|
||||
|
||||
kout << "Test der Zahlenausgabefunktion:" << endl
|
||||
<< "| dec | hex | bin |" << endl
|
||||
<< "+-------+-------+-------+" << endl;
|
||||
|
||||
for (unsigned short num = 0; num < 17; ++num) {
|
||||
kout << fillw(0) << "| " << fillw(6) << dec << num
|
||||
<< fillw(0) << "| " << fillw(6) << hex << num
|
||||
<< fillw(0) << "| " << fillw(6) << bin << num
|
||||
<< fillw(0) << "|" << endl;
|
||||
}
|
||||
|
||||
kout << endl;
|
||||
|
||||
kout.unlock();
|
||||
scheduler.exit();
|
||||
}
|
26
src/kernel/demo/TextDemo.h
Executable file
26
src/kernel/demo/TextDemo.h
Executable file
@ -0,0 +1,26 @@
|
||||
/*****************************************************************************
|
||||
* *
|
||||
* T E X T D E M O *
|
||||
* *
|
||||
*---------------------------------------------------------------------------*
|
||||
* Beschreibung: Testausgaben für den CGA-Treiber. *
|
||||
* *
|
||||
* Autor: Michael Schoettner, HHU, 26.10.2018 *
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef TextDemo_include__
|
||||
#define TextDemo_include__
|
||||
|
||||
#include "kernel/system/Globals.h"
|
||||
#include "kernel/process/Thread.h"
|
||||
|
||||
class TextDemo : public Thread {
|
||||
public:
|
||||
TextDemo(const TextDemo& copy) = delete;
|
||||
|
||||
TextDemo() : Thread("TextDemo") {}
|
||||
|
||||
void run() override;
|
||||
};
|
||||
|
||||
#endif
|
106
src/kernel/demo/VBEdemo.cc
Normal file
106
src/kernel/demo/VBEdemo.cc
Normal file
@ -0,0 +1,106 @@
|
||||
/*****************************************************************************
|
||||
* *
|
||||
* V B E D E M O *
|
||||
* *
|
||||
*---------------------------------------------------------------------------*
|
||||
* Beschreibung: Demo zu VESA. *
|
||||
* *
|
||||
* Autor: Michael Schoettner, HHU, 26.12.2016 *
|
||||
*****************************************************************************/
|
||||
|
||||
#include "VBEdemo.h"
|
||||
#include "bmp_hhu.cc"
|
||||
|
||||
/*****************************************************************************
|
||||
* Methode: VBEdemo::linInterPol1D *
|
||||
*---------------------------------------------------------------------------*
|
||||
* Beschreibung: Farbwert in einer Dimension interpoliert berechnen. *
|
||||
*****************************************************************************/
|
||||
int VBEdemo::linInterPol1D(int x, int xr, int l, int r) {
|
||||
return ((((l >> 16) * (xr - x) + (r >> 16) * x) / xr) << 16) | (((((l >> 8) & 0xFF) * (xr - x) + ((r >> 8) & 0xFF) * x) / xr) << 8) | (((l & 0xFF) * (xr - x) + (r & 0xFF) * x) / xr);
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* Methode: VBEdemo::linInterPol2D *
|
||||
*---------------------------------------------------------------------------*
|
||||
* Beschreibung: Farbwert in zwei Dimensionen interpoliert berechnen. *
|
||||
*****************************************************************************/
|
||||
int VBEdemo::linInterPol2D(int x, int y, int lt, int rt, int lb, int rb) {
|
||||
return linInterPol1D(y, vesa.yres,
|
||||
linInterPol1D(x, vesa.xres, lt, rt),
|
||||
linInterPol1D(x, vesa.xres, lb, rb));
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* Methode: VBEdemo::drawColors *
|
||||
*---------------------------------------------------------------------------*
|
||||
* Beschreibung: Pixel-Demo. *
|
||||
*****************************************************************************/
|
||||
void VBEdemo::drawColors() {
|
||||
int x_res = 640;
|
||||
int y_res = 480;
|
||||
|
||||
for (int y = 0; y < y_res; y++) {
|
||||
for (int x = 0; x < x_res; x++) {
|
||||
vesa.drawPixel(x, y, linInterPol2D(x, y, 0x0000FF, 0x00FF00, 0xFF0000, 0xFFFF00));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* Methode: VBEdemo::drawBitmap *
|
||||
*---------------------------------------------------------------------------*
|
||||
* Beschreibung: Bitmap aus GIMP ausgeben. *
|
||||
*****************************************************************************/
|
||||
void VBEdemo::drawBitmap() {
|
||||
unsigned int sprite_width = hhu.width;
|
||||
unsigned int sprite_height = hhu.height;
|
||||
unsigned int sprite_bpp = hhu.bytes_per_pixel;
|
||||
const unsigned char* sprite_pixel = reinterpret_cast<const unsigned char*>(hhu.pixel_data);
|
||||
|
||||
/* Hier muss Code eingefuegt werden */
|
||||
|
||||
vesa.drawSprite(sprite_width, sprite_height, sprite_bpp, sprite_pixel);
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* Methode: VBEdemo::drawFonts *
|
||||
*---------------------------------------------------------------------------*
|
||||
* Beschreibung: Fonts ausgeben. *
|
||||
*****************************************************************************/
|
||||
void VBEdemo::drawFonts() {
|
||||
|
||||
/* Hier muss Code eingefuegt werden */
|
||||
|
||||
vesa.drawString(std_font_8x8, 0, 300, 0, "STD FONT 8x8", 12);
|
||||
vesa.drawString(std_font_8x16, 0, 320, 0, "STD FONT 8x16", 13);
|
||||
vesa.drawString(acorn_font_8x8, 0, 340, 0, "ACORN FONT 8x8", 14);
|
||||
vesa.drawString(sun_font_8x16, 0, 360, 0, "SUN FONT 8x16", 13);
|
||||
vesa.drawString(sun_font_12x22, 0, 380, 0, "SUN FONT 12x22", 14);
|
||||
vesa.drawString(pearl_font_8x8, 0, 400, 0, "PEARL FONT 8x8", 14);
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* Methode: VBEdemo::run *
|
||||
*---------------------------------------------------------------------------*
|
||||
* Beschreibung: Der Anwendungsthread erzeugt drei Threads die Zaehler *
|
||||
* ausgeben und terminiert sich selbst. *
|
||||
*****************************************************************************/
|
||||
void VBEdemo::run() {
|
||||
|
||||
// In den Grafikmodus schalten (32-Bit Farbtiefe)
|
||||
vesa.initGraphicMode(MODE_640_480_24BITS);
|
||||
vesa.setDrawingBuff(BUFFER_VISIBLE);
|
||||
|
||||
drawColors();
|
||||
|
||||
/* Hier muss Code eingefuegt werden */
|
||||
vesa.drawRectangle(100, 100, 300, 300, 0);
|
||||
drawBitmap();
|
||||
drawFonts();
|
||||
|
||||
while (running) {}
|
||||
|
||||
// selbst terminieren
|
||||
scheduler.exit();
|
||||
}
|
46
src/kernel/demo/VBEdemo.h
Normal file
46
src/kernel/demo/VBEdemo.h
Normal file
@ -0,0 +1,46 @@
|
||||
/*****************************************************************************
|
||||
* *
|
||||
* V B E D E M O *
|
||||
* *
|
||||
*---------------------------------------------------------------------------*
|
||||
* Beschreibung: Demo zu VESA. *
|
||||
* *
|
||||
* Autor: Michael Schoettner, HHU, 26.12.2016 *
|
||||
*****************************************************************************/
|
||||
#ifndef VBEdemo_include__
|
||||
#define VBEdemo_include__
|
||||
|
||||
#include "kernel/system/Globals.h"
|
||||
#include "kernel/process/Thread.h"
|
||||
|
||||
class VBEdemo : public Thread {
|
||||
private:
|
||||
// Hilfsfunktionen fuer drawColors()
|
||||
static int linInterPol1D(int x, int xr, int l, int r);
|
||||
static int linInterPol2D(int x, int y, int lt, int rt, int lb, int rb);
|
||||
|
||||
public:
|
||||
VBEdemo(const VBEdemo& copy) = delete; // Verhindere Kopieren
|
||||
|
||||
// Gib dem Anwendungsthread einen Stack.
|
||||
VBEdemo() : Thread("VBEdemo") {}
|
||||
|
||||
~VBEdemo() override {
|
||||
allocator.free(reinterpret_cast<void*>(vesa.hfb)); // Memory is allocated after every start and never deleted, so add that
|
||||
VESA::initTextMode();
|
||||
}
|
||||
|
||||
// Thread-Startmethode
|
||||
void run() override;
|
||||
|
||||
// Farbraum ausgeben
|
||||
void drawColors();
|
||||
|
||||
// Bitmap aus GIMP ausgeben
|
||||
static void drawBitmap();
|
||||
|
||||
// Fonts ausgeben
|
||||
static void drawFonts();
|
||||
};
|
||||
|
||||
#endif
|
110
src/kernel/demo/VectorDemo.cc
Normal file
110
src/kernel/demo/VectorDemo.cc
Normal file
@ -0,0 +1,110 @@
|
||||
#include "VectorDemo.h"
|
||||
|
||||
void print(OutStream& os, const bse::vector<int>& list) {
|
||||
os << "Printing List: ";
|
||||
for (const int i : list) {
|
||||
os << i << " ";
|
||||
}
|
||||
os << endl;
|
||||
}
|
||||
|
||||
void VectorDemo::run() {
|
||||
bse::vector<int> list;
|
||||
|
||||
kout.lock();
|
||||
kout.clear();
|
||||
kout << "Logs are written to serial to see the memory interactions" << endl;
|
||||
|
||||
log.info() << "Initial list size: " << dec << list.size() << endl;
|
||||
|
||||
log.info() << "Adding elements in order" << endl;
|
||||
for (int i = 0; i < 5; ++i) {
|
||||
list.push_back(i);
|
||||
}
|
||||
print(log.info(), list);
|
||||
|
||||
log.info() << "Removing all elements from the front" << endl;
|
||||
for (unsigned int i = 0; i < 5; ++i) {
|
||||
list.erase(list.begin());
|
||||
}
|
||||
print(log.info(), list);
|
||||
|
||||
// ============================================================
|
||||
|
||||
log.info() << "Adding elements in order with realloc" << endl;
|
||||
for (int i = 0; i < 10; ++i) {
|
||||
log.info() << "Add " << dec << i << endl;
|
||||
list.push_back(i);
|
||||
}
|
||||
print(log.info(), list);
|
||||
|
||||
log.info() << "Removing all elements from the back" << endl;
|
||||
for (unsigned int i = 0; i < 10; ++i) {
|
||||
list.erase(list.end() - 1);
|
||||
}
|
||||
print(log.info(), list);
|
||||
|
||||
// ============================================================
|
||||
|
||||
for (int i = 0; i < 5; ++i) {
|
||||
list.push_back(i);
|
||||
}
|
||||
print(log.info(), list);
|
||||
|
||||
log.info() << "Adding inside the list (at idx 0, 2, 5)" << endl;
|
||||
list.insert(list.begin() + 0, 10);
|
||||
list.insert(list.begin() + 2, 10);
|
||||
list.insert(list.begin() + 5, 10);
|
||||
print(log.info(), list);
|
||||
|
||||
log.info() << "Removing inside the list (at idx 0, 2, 5)" << endl;
|
||||
list.erase(list.begin() + 0);
|
||||
list.erase(list.begin() + 2);
|
||||
list.erase(list.begin() + 5);
|
||||
print(log.info(), list);
|
||||
|
||||
for (unsigned int i = 0; i < 5; ++i) {
|
||||
list.erase(list.begin());
|
||||
}
|
||||
print(log.info(), list);
|
||||
|
||||
// ============================================================
|
||||
|
||||
log.info() << "Mirror scheduling behavior" << endl;
|
||||
|
||||
// These are the threads
|
||||
int active = 0; // Idle thread
|
||||
list.push_back(1);
|
||||
list.push_back(2);
|
||||
list.push_back(3);
|
||||
print(log.info(), list);
|
||||
|
||||
log.info() << "Starting..." << endl;
|
||||
for (unsigned int n = 0; n < 10000; ++n) {
|
||||
list.push_back(active);
|
||||
active = list[0];
|
||||
list.erase(list.begin());
|
||||
|
||||
if (list.size() != 3 || active == -1) {
|
||||
log.info() << "ERROR: Thread went missing" << endl;
|
||||
break;
|
||||
}
|
||||
|
||||
if (n < 5) {
|
||||
print(log.info(), list);
|
||||
}
|
||||
}
|
||||
log.info() << "Finished." << endl;
|
||||
|
||||
print(log.info(), list);
|
||||
|
||||
// ============================================================
|
||||
|
||||
log.info() << "Range based for support" << endl;
|
||||
for (int i : list) {
|
||||
log.info() << "List contains element: " << dec << i << endl;
|
||||
}
|
||||
|
||||
kout.unlock();
|
||||
scheduler.exit();
|
||||
}
|
17
src/kernel/demo/VectorDemo.h
Normal file
17
src/kernel/demo/VectorDemo.h
Normal file
@ -0,0 +1,17 @@
|
||||
#ifndef VectorDemo_include__
|
||||
#define VectorDemo_include__
|
||||
|
||||
#include "kernel/system/Globals.h"
|
||||
#include "kernel/process/Thread.h"
|
||||
#include "lib/util/Vector.h"
|
||||
|
||||
class VectorDemo : public Thread {
|
||||
public:
|
||||
VectorDemo(const VectorDemo& copy) = delete;
|
||||
|
||||
VectorDemo() : Thread("VectorDemo") {}
|
||||
|
||||
void run() override;
|
||||
};
|
||||
|
||||
#endif
|
1576
src/kernel/demo/bmp_hhu.cc
Normal file
1576
src/kernel/demo/bmp_hhu.cc
Normal file
File diff suppressed because it is too large
Load Diff
12
src/kernel/event/KeyEventListener.cc
Normal file
12
src/kernel/event/KeyEventListener.cc
Normal file
@ -0,0 +1,12 @@
|
||||
#include "kernel/event/KeyEventListener.h"
|
||||
#include "kernel/system/Globals.h"
|
||||
|
||||
void KeyEventListener::trigger(char c) {
|
||||
lastChar = c;
|
||||
}
|
||||
|
||||
char KeyEventListener::waitForKeyEvent() const {
|
||||
Logger::instance() << DEBUG << "KEvLis:: Thread with id: " << tid << " waiting for key event" << endl;
|
||||
scheduler.block();
|
||||
return lastChar; // This is only executed after thread is woken up by manager
|
||||
}
|
22
src/kernel/event/KeyEventListener.h
Normal file
22
src/kernel/event/KeyEventListener.h
Normal file
@ -0,0 +1,22 @@
|
||||
#ifndef KeyEventListener_Include_H_
|
||||
#define KeyEventListener_Include_H_
|
||||
|
||||
#include "kernel/process/Thread.h"
|
||||
|
||||
class KeyEventListener {
|
||||
private:
|
||||
char lastChar = '\0';
|
||||
|
||||
friend class KeyEventManager;
|
||||
unsigned int tid; // Thread which contains this listener, so the listener can block the thread
|
||||
|
||||
public:
|
||||
KeyEventListener(const KeyEventListener& copy) = delete;
|
||||
|
||||
KeyEventListener(unsigned int tid) : tid(tid) {}
|
||||
|
||||
char waitForKeyEvent() const; // Blocks the thread until woken up by manager
|
||||
void trigger(char c); // Gets called from KeyEventManager
|
||||
};
|
||||
|
||||
#endif
|
26
src/kernel/event/KeyEventManager.cc
Normal file
26
src/kernel/event/KeyEventManager.cc
Normal file
@ -0,0 +1,26 @@
|
||||
#include "KeyEventManager.h"
|
||||
#include "kernel/system/Globals.h"
|
||||
|
||||
void KeyEventManager::subscribe(KeyEventListener& sub) {
|
||||
log.debug() << "Subscribe, Thread ID: " << dec << sub.tid << endl;
|
||||
listeners.push_back(&sub);
|
||||
}
|
||||
|
||||
void KeyEventManager::unsubscribe(KeyEventListener& unsub) {
|
||||
log.debug() << "Unsubscribe, Thread ID: " << dec << unsub.tid << endl;
|
||||
for (bse::vector<KeyEventListener*>::iterator it = listeners.begin(); it != listeners.end(); ++it) {
|
||||
if ((*it)->tid == unsub.tid) {
|
||||
listeners.erase(it);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void KeyEventManager::broadcast(char c) {
|
||||
log.trace() << "Beginning Broadcast" << endl;
|
||||
for (KeyEventListener* listener : listeners) {
|
||||
log.trace() << "Broadcasting " << c << " to Thread ID: " << dec << listener->tid << endl;
|
||||
listener->trigger(c);
|
||||
scheduler.deblock(listener->tid);
|
||||
}
|
||||
}
|
31
src/kernel/event/KeyEventManager.h
Normal file
31
src/kernel/event/KeyEventManager.h
Normal file
@ -0,0 +1,31 @@
|
||||
#ifndef KeyEventManager_Include_H_
|
||||
#define KeyEventManager_Include_H_
|
||||
|
||||
#include "kernel/event/KeyEventListener.h"
|
||||
#include "kernel/log/Logger.h"
|
||||
#include "lib/util/Vector.h"
|
||||
|
||||
// NOTE: Could do this more generally but we only have key events
|
||||
// Also pretty limited: One thread can have one listener as identification is done over tid
|
||||
|
||||
class KeyEventManager {
|
||||
private:
|
||||
NamedLogger log;
|
||||
|
||||
bse::vector<KeyEventListener*> listeners;
|
||||
|
||||
public:
|
||||
KeyEventManager(const KeyEventManager& copy) = delete;
|
||||
|
||||
KeyEventManager() : log("KEvMan"), listeners(true) {}
|
||||
|
||||
void init() {
|
||||
listeners.reserve();
|
||||
}
|
||||
|
||||
void subscribe(KeyEventListener& sub);
|
||||
void unsubscribe(KeyEventListener& unsub);
|
||||
void broadcast(char c); // Unblocks all input waiting threads, I don't have a method to direct input
|
||||
};
|
||||
|
||||
#endif
|
305
src/kernel/interrupt/Bluescreen.cc
Normal file
305
src/kernel/interrupt/Bluescreen.cc
Normal file
@ -0,0 +1,305 @@
|
||||
/*****************************************************************************
|
||||
* *
|
||||
* B L U E S C R E E N *
|
||||
* *
|
||||
*---------------------------------------------------------------------------*
|
||||
* Beschreibung: Ein Bluescreen, falls eine x86 Exception auftritt. Evt. *
|
||||
* ist der Stack und oder Heap kaputt, weswegen hier nicht *
|
||||
* kout etc. verwendet wird. *
|
||||
* *
|
||||
* Autor: Michael Schoettner, 11.12.2018 *
|
||||
*****************************************************************************/
|
||||
#include "kernel/system/Globals.h"
|
||||
|
||||
// in startup.asm
|
||||
extern "C" {
|
||||
// CR2 auslesen
|
||||
unsigned int get_page_fault_address();
|
||||
|
||||
// 1st level interrupt handler in startup.asm sichert Zeiger auf Stackframe
|
||||
// unmittelbar nach dem Interrupt und nachdem alle Register mit PUSHAD
|
||||
// gesichert wurden
|
||||
// |-------------|
|
||||
// | EFLAGS |
|
||||
// |-------------|
|
||||
// | CS |
|
||||
// |-------------|
|
||||
// | EIP |
|
||||
// |-------------|
|
||||
// | [ErrorCode] |
|
||||
// |-------------|
|
||||
// | EAX |
|
||||
// |-------------|
|
||||
// | ECX |
|
||||
// |-------------|
|
||||
// | EDX |
|
||||
// |-------------|
|
||||
// | EBX |
|
||||
// |-------------|
|
||||
// | ESP |
|
||||
// |-------------|
|
||||
// | EBP |
|
||||
// |-------------|
|
||||
// | ESI |
|
||||
// |-------------|
|
||||
// | EDI |
|
||||
// |-------------| <-- int_esp
|
||||
|
||||
void get_int_esp(unsigned int** esp);
|
||||
}
|
||||
|
||||
void break_on_bluescreen() {
|
||||
|
||||
/* wenn auf diese Methode ein breakpoint in GDB gesetzt wird
|
||||
so kann man sich mithilfe des Hex-Dumps umsehen
|
||||
*/
|
||||
}
|
||||
|
||||
// Cursor-Position
|
||||
int bs_xpos = 0;
|
||||
int bs_ypos = 0;
|
||||
|
||||
/*****************************************************************************
|
||||
* Funktion: bs_clear *
|
||||
*---------------------------------------------------------------------------*
|
||||
* Beschreibung: Bildschirm loeschen. *
|
||||
*****************************************************************************/
|
||||
void bs_clear() {
|
||||
unsigned int x;
|
||||
unsigned int y;
|
||||
unsigned short* ptr = reinterpret_cast<unsigned short*>(0xb8000);
|
||||
|
||||
for (x = 0; x < 80; x++) {
|
||||
for (y = 0; y < 25; y++) {
|
||||
*(ptr + y * 80 + x) = static_cast<short>(0x1F00);
|
||||
}
|
||||
}
|
||||
|
||||
bs_xpos = 0;
|
||||
bs_ypos = 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* Funktion: bs_lf *
|
||||
*---------------------------------------------------------------------------*
|
||||
* Beschreibung: Zeilenvorschub. *
|
||||
*****************************************************************************/
|
||||
void bs_lf() {
|
||||
bs_ypos++;
|
||||
bs_xpos = 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* Funktion: bs_print_char *
|
||||
*---------------------------------------------------------------------------*
|
||||
* Beschreibung: Ein Zeichen ausgeben. *
|
||||
*****************************************************************************/
|
||||
void bs_print_char(char c) {
|
||||
unsigned char* ptr = reinterpret_cast<unsigned char*>(0xb8000);
|
||||
|
||||
*(ptr + bs_ypos * 80 * 2 + bs_xpos * 2) = c;
|
||||
bs_xpos++;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* Funktion: bs_print_string *
|
||||
*---------------------------------------------------------------------------*
|
||||
* Beschreibung: Eine Zeichenkette ausgeben. *
|
||||
*****************************************************************************/
|
||||
void bs_print_string(char* str) {
|
||||
|
||||
while (*str != '\0') {
|
||||
bs_print_char(*str);
|
||||
str++;
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* Funktion: bs_printHexDigit *
|
||||
*---------------------------------------------------------------------------*
|
||||
* Beschreibung: Ein Hex-Zeichen ausgeben. *
|
||||
*****************************************************************************/
|
||||
void bs_printHexDigit(int c) {
|
||||
if (c < 10) {
|
||||
bs_print_char('0' + static_cast<unsigned char>(c));
|
||||
} else {
|
||||
bs_print_char('A' + static_cast<unsigned char>(c - 10));
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* Funktion: bs_print_uintHex *
|
||||
*---------------------------------------------------------------------------*
|
||||
* Beschreibung: Integer ausgeben. *
|
||||
*****************************************************************************/
|
||||
void bs_print_uintHex(unsigned int c) {
|
||||
for (int i = 28; i >= 0; i = i - 4) {
|
||||
bs_printHexDigit((c >> i) & 0xF);
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* Funktion: bs_printReg *
|
||||
*---------------------------------------------------------------------------*
|
||||
* Beschreibung: String mit Integer ausgeben. Wird verwendet um ein *
|
||||
* Register auszugeben. *
|
||||
*****************************************************************************/
|
||||
void bs_printReg(char* str, unsigned int value) {
|
||||
bs_print_string(str);
|
||||
bs_print_uintHex(value);
|
||||
bs_print_string(" \0");
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* Funktion: bs_dump *
|
||||
*---------------------------------------------------------------------------*
|
||||
* Beschreibung: Hauptroutine des Bluescreens. *
|
||||
*****************************************************************************/
|
||||
void bs_dump(unsigned int exceptionNr) {
|
||||
unsigned int* int_esp;
|
||||
unsigned int* sptr;
|
||||
unsigned int faultAdress;
|
||||
unsigned int has_error_code = 0;
|
||||
|
||||
bs_clear();
|
||||
bs_print_string("HHUos crashed with Exception \0");
|
||||
|
||||
// Exception mit Error-Code?
|
||||
if ((exceptionNr >= 8 && exceptionNr <= 14) || exceptionNr == 17 || exceptionNr == 30) {
|
||||
has_error_code = 1;
|
||||
}
|
||||
|
||||
// Liegt ein Page-Fault vor?
|
||||
if (exceptionNr == 14) {
|
||||
faultAdress = get_page_fault_address();
|
||||
// Zugriff auf Seite 0 ? -> Null-Ptr. Exception
|
||||
if ((faultAdress & 0xFFFFF000) == 0) {
|
||||
exceptionNr = 0x1B;
|
||||
}
|
||||
}
|
||||
|
||||
bs_print_uintHex(exceptionNr);
|
||||
bs_print_string(" (\0");
|
||||
|
||||
// Spruch ausgeben
|
||||
switch (exceptionNr) {
|
||||
case 0x00: bs_print_string("Divide Error\0"); break;
|
||||
case 0x01: bs_print_string("Debug Exception\0"); break;
|
||||
case 0x02: bs_print_string("NMI\0"); break;
|
||||
case 0x03: bs_print_string("Breakpoint Exception\0"); break;
|
||||
case 0x04: bs_print_string("Into Exception\0"); break;
|
||||
case 0x05: bs_print_string("Index out of range Exception\0"); break;
|
||||
case 0x06: bs_print_string("Invalid Opcode\0"); break;
|
||||
case 0x08: bs_print_string("Double Fault\0"); break;
|
||||
case 0x0D: bs_print_string("General Protection Error\0"); break;
|
||||
case 0x0E: bs_print_string("Page Fault\0"); break;
|
||||
case 0x18: bs_print_string("Stack invalid\0"); break;
|
||||
case 0x19: bs_print_string("Return missing\0"); break;
|
||||
case 0x1A: bs_print_string("Type Test Failed\0"); break;
|
||||
case 0x1B: bs_print_string("Null pointer exception\0"); break;
|
||||
case 0x1C: bs_print_string("MAGIC.StackTest failed\0"); break;
|
||||
case 0x1D: bs_print_string("Memory-Panic\0"); break;
|
||||
case 0x1E: bs_print_string("Pageload failed\0"); break;
|
||||
case 0x1F: bs_print_string("Stack overflow\0"); break;
|
||||
default: bs_print_string("unknown\0");
|
||||
}
|
||||
bs_print_string(")\0");
|
||||
bs_lf();
|
||||
|
||||
// Zeiger auf int_esp ueber startup.asm beschaffen (Stack-Layout siehe Anfang dieser Datei)
|
||||
get_int_esp(&int_esp);
|
||||
|
||||
// wir müssen den Inhalt auslesen und das als Zeiger verwenden, um den Stack auszulesen
|
||||
sptr = reinterpret_cast<unsigned int*>(*int_esp);
|
||||
|
||||
bs_lf();
|
||||
|
||||
// wichtigste Register ausgeben
|
||||
|
||||
// Exception mit Error-Code?
|
||||
bs_printReg("EIP=\0", *(sptr + 8 + has_error_code));
|
||||
bs_printReg("EBP=\0", *(sptr + 2));
|
||||
bs_printReg("ESP=\0", *(sptr + 3));
|
||||
bs_printReg(" CS=\0", *(sptr + 9 + has_error_code));
|
||||
bs_lf();
|
||||
|
||||
// verbleibende nicht-fluechtige Register ausgeben
|
||||
bs_printReg("EBX=\0", *(sptr + 4));
|
||||
bs_printReg("ESI=\0", *(sptr + 1));
|
||||
bs_printReg("EDI=\0", *(sptr));
|
||||
bs_lf();
|
||||
|
||||
// verbleibende fluechtige Register ausgeben
|
||||
bs_printReg("EDX=\0", *(sptr + 5));
|
||||
bs_printReg("ECX=\0", *(sptr + 6));
|
||||
bs_printReg("EAX=\0", *(sptr + 7));
|
||||
bs_printReg("EFL=\0", *(sptr + 10));
|
||||
bs_lf();
|
||||
|
||||
// Pagefault oder Null-Pointer?
|
||||
if (exceptionNr == 14 || exceptionNr == 0x1B) {
|
||||
bs_lf();
|
||||
bs_print_string("Fault address = \0");
|
||||
bs_print_uintHex(faultAdress);
|
||||
bs_lf();
|
||||
|
||||
bs_print_string("Last useable address = \0");
|
||||
bs_print_uintHex(total_mem - 1);
|
||||
|
||||
bs_lf();
|
||||
}
|
||||
|
||||
// Exception mit Error-Code?
|
||||
if (has_error_code == 1) {
|
||||
unsigned int error_nr = *(sptr + 8);
|
||||
|
||||
if (exceptionNr == 14) {
|
||||
if (error_nr == 3) {
|
||||
bs_print_string("Error: write access to read-only page.\0");
|
||||
} else if (error_nr == 2) {
|
||||
bs_print_string("Error: read access to not-present page.\0");
|
||||
} else if (error_nr == 0) {
|
||||
bs_print_string("Error: access to a not-present page.\0");
|
||||
} else {
|
||||
bs_print_string("Error code = \0");
|
||||
bs_print_uintHex(error_nr);
|
||||
}
|
||||
bs_lf();
|
||||
} else {
|
||||
bs_print_string("Error code = \0");
|
||||
bs_print_uintHex(error_nr);
|
||||
bs_lf();
|
||||
}
|
||||
}
|
||||
|
||||
// Calling stack ...
|
||||
bs_lf();
|
||||
bs_print_string("Calling Stack:\0");
|
||||
bs_lf();
|
||||
int x = 0;
|
||||
unsigned int* ebp = reinterpret_cast<unsigned int*>(*(sptr + 2));
|
||||
unsigned int raddr;
|
||||
|
||||
// solange eip > 1 MB && ebp < 128 MB, max. Aufruftiefe 10
|
||||
while (*ebp > 0x100000 && *ebp < 0x8000000 && x < 10) {
|
||||
|
||||
raddr = *(ebp + 1);
|
||||
bs_printReg(" raddr=\0", raddr);
|
||||
bs_lf();
|
||||
|
||||
// dynamische Kette -> zum Aufrufer
|
||||
ebp = reinterpret_cast<unsigned int*>(*ebp);
|
||||
|
||||
x++;
|
||||
}
|
||||
if (x == 0) {
|
||||
bs_print_string(" empty\0");
|
||||
bs_lf();
|
||||
}
|
||||
bs_lf();
|
||||
|
||||
// nur falls gdb benutzt werden soll
|
||||
break_on_bluescreen();
|
||||
|
||||
bs_print_string("System halted\0");
|
||||
}
|
19
src/kernel/interrupt/Bluescreen.h
Normal file
19
src/kernel/interrupt/Bluescreen.h
Normal file
@ -0,0 +1,19 @@
|
||||
/*****************************************************************************
|
||||
* *
|
||||
* B L U E S C R E E N *
|
||||
* *
|
||||
*---------------------------------------------------------------------------*
|
||||
* Beschreibung: Ein Bluescreen, falls eine x86 Exception auftritt. Evt. *
|
||||
* ist der Stack und oder Heap kaputt, weswegen hier nicht *
|
||||
* kout etc. verwendet wird. *
|
||||
* *
|
||||
* Autor: Michael Schoettner, 2.2.2017 *
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef Bluescreen_include__
|
||||
#define Bluescreen_include__
|
||||
|
||||
// dump blue screen (will not return)
|
||||
void bs_dump(unsigned int exceptionNr);
|
||||
|
||||
#endif
|
27
src/kernel/interrupt/ISR.h
Executable file
27
src/kernel/interrupt/ISR.h
Executable file
@ -0,0 +1,27 @@
|
||||
/*****************************************************************************
|
||||
* *
|
||||
* I S R *
|
||||
* *
|
||||
*---------------------------------------------------------------------------*
|
||||
* Beschreibung: Interrupt Service Routine. Jeweils ein Objekt pro ISR. *
|
||||
* Erlaubt es einen Kontext mit Variablen fuer die Unter- *
|
||||
* brechungsroutine bereitzustellen. *
|
||||
* *
|
||||
* Autor: Michael Schoettner, 06.04.20 *
|
||||
*****************************************************************************/
|
||||
#ifndef ISR_include__
|
||||
#define ISR_include__
|
||||
|
||||
class ISR {
|
||||
public:
|
||||
ISR(const ISR& copy) = delete; // Verhindere Kopieren
|
||||
|
||||
// virtual ~ISR() = default;
|
||||
|
||||
ISR() = default;
|
||||
|
||||
// Unterbrechungsbehandlungsroutine
|
||||
virtual void trigger() = 0;
|
||||
};
|
||||
|
||||
#endif
|
109
src/kernel/interrupt/IntDispatcher.cc
Executable file
109
src/kernel/interrupt/IntDispatcher.cc
Executable file
@ -0,0 +1,109 @@
|
||||
/*****************************************************************************
|
||||
* *
|
||||
* I N T D I S P A T C H E R *
|
||||
* *
|
||||
*---------------------------------------------------------------------------*
|
||||
* Beschreibung: Zentrale Unterbrechungsbehandlungsroutine des Systems. *
|
||||
* Der Parameter gibt die Nummer des aufgetretenen *
|
||||
* Interrupts an. Wenn eine Interrupt Service Routine *
|
||||
* registriert ist, wird diese aufgerufen. *
|
||||
* *
|
||||
* Autor: Michael Schoettner, 31.8.2016 *
|
||||
*****************************************************************************/
|
||||
#include "IntDispatcher.h"
|
||||
#include "device/cpu/CPU.h"
|
||||
#include "kernel/system/Globals.h"
|
||||
#include "kernel/interrupt/Bluescreen.h"
|
||||
|
||||
extern "C" void int_disp(unsigned int vector);
|
||||
|
||||
/*****************************************************************************
|
||||
* Prozedur: int_disp *
|
||||
*---------------------------------------------------------------------------*
|
||||
* Beschreibung: Low-Level Interrupt-Behandlung. *
|
||||
* Diese Funktion ist in der IDT fuer alle Eintraege einge- *
|
||||
* tragen. Dies geschieht bereits im Bootloader. *
|
||||
* Sie wird also fuer alle Interrupts aufgerufen. Von hier *
|
||||
* aus sollen die passenden ISR-Routinen der Treiber-Objekte*
|
||||
* mithilfe von 'IntDispatcher::report' aufgerufen werden. *
|
||||
* Parameter: *
|
||||
* vector: Vektor-Nummer der Unterbrechung *
|
||||
*****************************************************************************/
|
||||
void int_disp(unsigned int vector) {
|
||||
|
||||
/* hier muss Code eingefuegt werden */
|
||||
|
||||
if (vector < 32) {
|
||||
bs_dump(vector);
|
||||
CPU::halt();
|
||||
}
|
||||
|
||||
if (intdis.report(vector) < 0) {
|
||||
kout << "Panic: unexpected interrupt " << vector;
|
||||
kout << " - processor halted." << endl;
|
||||
CPU::halt();
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* Methode: IntDispatcher::assign *
|
||||
*---------------------------------------------------------------------------*
|
||||
* Beschreibung: Registrierung einer ISR. *
|
||||
* *
|
||||
* Parameter: *
|
||||
* vector: Vektor-Nummer der Unterbrechung *
|
||||
* isr: ISR die registriert werden soll *
|
||||
* *
|
||||
* Rueckgabewert: 0 = Erfolg, -1 = Fehler *
|
||||
*****************************************************************************/
|
||||
int IntDispatcher::assign(unsigned int vector, ISR& isr) {
|
||||
|
||||
/* hier muss Code eingefuegt werden */
|
||||
|
||||
if (vector >= size) {
|
||||
log.error() << "Invalid vector number when assigning" << endl;
|
||||
return -1;
|
||||
}
|
||||
|
||||
map[vector] = &isr;
|
||||
log.info() << "Registered ISR for vector " << dec << vector << endl;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* Methode: IntDispatcher::report *
|
||||
*---------------------------------------------------------------------------*
|
||||
* Beschreibung: Eingetragene ISR ausfuehren. *
|
||||
* *
|
||||
* Parameter: *
|
||||
* vector: Gesuchtes ISR-Objekt fuer diese Vektor-Nummer. *
|
||||
* *
|
||||
* Rueckgabewert: 0 = ISR wurde aufgerufen, -1 = unbekannte Vektor-Nummer *
|
||||
*****************************************************************************/
|
||||
int IntDispatcher::report(unsigned int vector) {
|
||||
|
||||
/* hier muss Code eingefuegt werden */
|
||||
|
||||
if (vector >= size) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
ISR* isr = map[vector];
|
||||
|
||||
if (isr == nullptr) {
|
||||
log.error() << "No ISR registered for vector " << vector << endl;
|
||||
return -1;
|
||||
}
|
||||
|
||||
// 32 = Timer
|
||||
// 33 = Keyboard
|
||||
// log.trace() << "Interrupt: " << dec << vector << endl;
|
||||
if (vector == 33) {
|
||||
log.debug() << "Keyboard Interrupt" << endl;
|
||||
}
|
||||
|
||||
isr->trigger();
|
||||
|
||||
return 0;
|
||||
}
|
51
src/kernel/interrupt/IntDispatcher.h
Executable file
51
src/kernel/interrupt/IntDispatcher.h
Executable file
@ -0,0 +1,51 @@
|
||||
/*****************************************************************************
|
||||
* *
|
||||
* I N T D I S P A T C H E R *
|
||||
* *
|
||||
*---------------------------------------------------------------------------*
|
||||
* Beschreibung: Zentrale Unterbrechungsbehandlungsroutine des Systems. *
|
||||
* Der Parameter gibt die Nummer des aufgetretenen *
|
||||
* Interrupts an. Wenn eine Interrupt Service Routine (ISR) *
|
||||
* in der Map registriert ist, so wird diese aufgerufen. *
|
||||
* *
|
||||
* Autor: Michael Schoettner, 30.7.16 *
|
||||
*****************************************************************************/
|
||||
#ifndef IntDispatcher_include__
|
||||
#define IntDispatcher_include__
|
||||
|
||||
#include "ISR.h"
|
||||
#include "lib/util/Array.h"
|
||||
#include "kernel/log/Logger.h"
|
||||
|
||||
class IntDispatcher {
|
||||
private:
|
||||
NamedLogger log;
|
||||
|
||||
enum { size = 256 };
|
||||
bse::array<ISR*, size> map;
|
||||
|
||||
public:
|
||||
IntDispatcher(const IntDispatcher& copy) = delete; // Verhindere Kopieren
|
||||
|
||||
// Vektor-Nummern
|
||||
enum {
|
||||
timer = 32,
|
||||
keyboard = 33,
|
||||
com1 = 36
|
||||
};
|
||||
|
||||
// Initialisierung der ISR map mit einer Default-ISR.
|
||||
IntDispatcher() : log("IntDis") {
|
||||
for (ISR*& slot : map) {
|
||||
slot = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
// Registrierung einer ISR. (Rueckgabewert: 0 = Erfolg, -1 = Fehler)
|
||||
int assign(unsigned int vector, ISR& isr);
|
||||
|
||||
// ISR fuer 'vector' ausfuehren
|
||||
int report(unsigned int vector);
|
||||
};
|
||||
|
||||
#endif
|
117
src/kernel/log/Logger.cc
Normal file
117
src/kernel/log/Logger.cc
Normal file
@ -0,0 +1,117 @@
|
||||
#include "Logger.h"
|
||||
#include "kernel/system/Globals.h"
|
||||
|
||||
bool Logger::kout_enabled = true;
|
||||
bool Logger::serial_enabled = true;
|
||||
|
||||
Logger::LogLevel Logger::level = Logger::ERROR;
|
||||
|
||||
constexpr const char* ansi_red = "\033[1;31m";
|
||||
constexpr const char* ansi_green = "\033[1;32m";
|
||||
constexpr const char* ansi_yellow = "\033[1;33m";
|
||||
constexpr const char* ansi_blue = "\033[1;34m";
|
||||
constexpr const char* ansi_magenta = "\033[1;35m";
|
||||
constexpr const char* ansi_cyan = "\033[1;36m";
|
||||
constexpr const char* ansi_white = "\033[1;37m";
|
||||
constexpr const char* ansi_default = "\033[0;39m ";
|
||||
|
||||
void Logger::log(const bse::string_view message, CGA::color col) const {
|
||||
if (Logger::kout_enabled) {
|
||||
CGA::color old_col = kout.color_fg;
|
||||
kout << fgc(col)
|
||||
<< Logger::level_to_string(current_message_level) << "::"
|
||||
<< message << fgc(old_col);
|
||||
kout.flush(); // Don't add newline, Logger already does that
|
||||
}
|
||||
if (Logger::serial_enabled) {
|
||||
switch (col) {
|
||||
case CGA::WHITE:
|
||||
SerialOut::write(ansi_white);
|
||||
break;
|
||||
case CGA::LIGHT_MAGENTA:
|
||||
SerialOut::write(ansi_magenta);
|
||||
break;
|
||||
case CGA::LIGHT_RED:
|
||||
SerialOut::write(ansi_red);
|
||||
break;
|
||||
case CGA::LIGHT_BLUE:
|
||||
SerialOut::write(ansi_blue);
|
||||
break;
|
||||
default:
|
||||
SerialOut::write(ansi_default);
|
||||
}
|
||||
SerialOut::write(Logger::level_to_string(current_message_level));
|
||||
SerialOut::write(":: ");
|
||||
SerialOut::write(message);
|
||||
SerialOut::write('\r');
|
||||
// serial.write("\r\n");
|
||||
}
|
||||
}
|
||||
|
||||
void Logger::flush() {
|
||||
buffer[pos] = '\0';
|
||||
|
||||
switch (current_message_level) {
|
||||
case Logger::TRACE:
|
||||
trace(buffer.data());
|
||||
break;
|
||||
case Logger::DEBUG:
|
||||
debug(buffer.data());
|
||||
break;
|
||||
case Logger::ERROR:
|
||||
error(buffer.data());
|
||||
break;
|
||||
case Logger::INFO:
|
||||
info(buffer.data());
|
||||
break;
|
||||
}
|
||||
|
||||
current_message_level = Logger::INFO;
|
||||
pos = 0;
|
||||
Logger::unlock();
|
||||
}
|
||||
|
||||
void Logger::trace(const bse::string_view message) const {
|
||||
if (Logger::level <= Logger::TRACE) {
|
||||
log(message, CGA::WHITE);
|
||||
}
|
||||
}
|
||||
|
||||
void Logger::debug(const bse::string_view message) const {
|
||||
if (Logger::level <= Logger::DEBUG) {
|
||||
log(message, CGA::LIGHT_MAGENTA);
|
||||
}
|
||||
}
|
||||
|
||||
void Logger::error(const bse::string_view message) const {
|
||||
if (Logger::level <= Logger::ERROR) {
|
||||
log(message, CGA::LIGHT_RED);
|
||||
}
|
||||
}
|
||||
|
||||
void Logger::info(const bse::string_view message) const {
|
||||
if (Logger::level <= Logger::INFO) {
|
||||
log(message, CGA::LIGHT_BLUE);
|
||||
}
|
||||
}
|
||||
|
||||
// Manipulatoren
|
||||
Logger& TRACE(Logger& log) {
|
||||
log.current_message_level = Logger::TRACE;
|
||||
return log;
|
||||
}
|
||||
|
||||
Logger& DEBUG(Logger& log) {
|
||||
log.current_message_level = Logger::DEBUG;
|
||||
return log;
|
||||
}
|
||||
|
||||
Logger& ERROR(Logger& log) {
|
||||
log.current_message_level = Logger::ERROR;
|
||||
return log;
|
||||
}
|
||||
|
||||
Logger& INFO(Logger& log) {
|
||||
log.current_message_level = Logger::INFO;
|
||||
return log;
|
||||
}
|
121
src/kernel/log/Logger.h
Normal file
121
src/kernel/log/Logger.h
Normal file
@ -0,0 +1,121 @@
|
||||
#ifndef Logger_Include_H_
|
||||
#define Logger_Include_H_
|
||||
|
||||
#include "device/graphics/CGA.h"
|
||||
#include "lib/stream/OutStream.h"
|
||||
#include "lib/async/SpinLock.h"
|
||||
#include "lib/util/String.h"
|
||||
#include "lib/util/StringView.h"
|
||||
|
||||
class Logger : public OutStream {
|
||||
public:
|
||||
static Logger& instance() {
|
||||
static Logger log;
|
||||
return log;
|
||||
}
|
||||
|
||||
private:
|
||||
Logger() = default;
|
||||
|
||||
static bool kout_enabled;
|
||||
static bool serial_enabled;
|
||||
|
||||
void log(const bse::string_view message, CGA::color col) const;
|
||||
|
||||
friend class NamedLogger; // Allow NamedLogger to lock/unlock
|
||||
|
||||
SpinLock sem; // Semaphore would be a cyclic include
|
||||
static void lock() { Logger::instance().sem.acquire(); }
|
||||
static void unlock() { Logger::instance().sem.release(); }
|
||||
// static void lock() {}
|
||||
// static void unlock() {}
|
||||
|
||||
public:
|
||||
// ~Logger() override = default;
|
||||
|
||||
Logger(const Logger& copy) = delete;
|
||||
void operator=(const Logger& copy) = delete;
|
||||
|
||||
enum LogLevel {
|
||||
TRACE,
|
||||
DEBUG,
|
||||
ERROR,
|
||||
INFO
|
||||
};
|
||||
static LogLevel level;
|
||||
LogLevel current_message_level = Logger::INFO; // Use this to log with manipulators
|
||||
|
||||
void flush() override;
|
||||
|
||||
void trace(const bse::string_view message) const;
|
||||
void debug(const bse::string_view message) const;
|
||||
void error(const bse::string_view message) const;
|
||||
void info(const bse::string_view message) const;
|
||||
|
||||
// TODO: Make lvl change accessible over menu
|
||||
static void set_level(LogLevel lvl) {
|
||||
Logger::level = lvl;
|
||||
}
|
||||
|
||||
static bse::string_view level_to_string(LogLevel lvl) {
|
||||
switch (lvl) {
|
||||
case Logger::TRACE:
|
||||
return "TRACE";
|
||||
case Logger::DEBUG:
|
||||
return "DEBUG";
|
||||
case Logger::ERROR:
|
||||
return "ERROR";
|
||||
case Logger::INFO:
|
||||
return "INFO";
|
||||
}
|
||||
}
|
||||
|
||||
static void enable_kout() {
|
||||
Logger::kout_enabled = true;
|
||||
}
|
||||
static void disable_kout() {
|
||||
Logger::kout_enabled = false;
|
||||
}
|
||||
static void enable_serial() {
|
||||
Logger::serial_enabled = true;
|
||||
}
|
||||
static void disable_serial() {
|
||||
Logger::serial_enabled = false;
|
||||
}
|
||||
};
|
||||
|
||||
// Manipulatoren
|
||||
Logger& TRACE(Logger& log);
|
||||
Logger& DEBUG(Logger& log);
|
||||
Logger& ERROR(Logger& log);
|
||||
Logger& INFO(Logger& log);
|
||||
|
||||
class NamedLogger {
|
||||
private:
|
||||
const char* name;
|
||||
|
||||
public:
|
||||
explicit NamedLogger(const char* name) : name(name) {}
|
||||
|
||||
Logger& trace() {
|
||||
Logger::lock();
|
||||
return Logger::instance() << TRACE << name << "::";
|
||||
}
|
||||
|
||||
Logger& debug() {
|
||||
Logger::lock();
|
||||
return Logger::instance() << DEBUG << name << "::";
|
||||
}
|
||||
|
||||
Logger& error() {
|
||||
Logger::lock();
|
||||
return Logger::instance() << ERROR << name << "::";
|
||||
}
|
||||
|
||||
Logger& info() {
|
||||
Logger::lock();
|
||||
return Logger::instance() << INFO << name << "::";
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
80
src/kernel/memory/Allocator.cc
Executable file
80
src/kernel/memory/Allocator.cc
Executable file
@ -0,0 +1,80 @@
|
||||
/*****************************************************************************
|
||||
* *
|
||||
* A L L O C A T O R *
|
||||
* *
|
||||
*---------------------------------------------------------------------------*
|
||||
* Beschreibung: Einfache Speicherverwaltung. 'new' und 'delete' werden *
|
||||
* durch Ueberladen der entsprechenden Operatoren *
|
||||
* realisiert. *
|
||||
* *
|
||||
* Memory-Laylout *
|
||||
* *
|
||||
* boot.asm *
|
||||
* 0x07c0: Bootsector vom BIOS geladen *
|
||||
* 0x0060: Boot-Code verschiebt sich hier hin *
|
||||
* 0x9000: Setup-Code (max. 64K inkl. Stack) vom *
|
||||
* Bootsector-Code geladen *
|
||||
* setup.asm *
|
||||
* 0x1000: System-Code (max. 512K) geladen *
|
||||
* System-Code *
|
||||
* 0x100000: System-Code, kopiert nach Umschalten in *
|
||||
* den Protected Mode kopiert (GRUB kann nur *
|
||||
* an Adressen >1M laden) *
|
||||
* Globale Variablen: Direkt nach dem Code liegen die globalen *
|
||||
* Variablen. *
|
||||
* Heap: *
|
||||
* 0x300000: Start-Adresse der Heap-Verwaltung *
|
||||
* 0x400000: Letzte Adresse des Heaps *
|
||||
* *
|
||||
* Achtung: Benötigt einen PC mit mindestens 8 MB RAM! *
|
||||
* *
|
||||
* Autor: Michael Schoettner, HHU, 1.3.2022 *
|
||||
*****************************************************************************/
|
||||
|
||||
#include "Allocator.h"
|
||||
#include "kernel/system/Globals.h"
|
||||
|
||||
constexpr const unsigned int MEM_SIZE_DEF = 8 * 1024 * 1024; // Groesse des Speichers = 8 MB
|
||||
constexpr const unsigned int HEAP_START = 0x300000; // Startadresse des Heaps
|
||||
constexpr const unsigned int HEAP_SIZE = 1024 * 1024; // Default-Groesse des Heaps, falls \
|
||||
// nicht über das BIOS ermittelbar
|
||||
|
||||
/*****************************************************************************
|
||||
* Konstruktor: Allocator::Allocator *
|
||||
*****************************************************************************/
|
||||
Allocator::Allocator() : heap_start(HEAP_START), heap_end(HEAP_START + HEAP_SIZE), heap_size(HEAP_SIZE), initialized(1) {
|
||||
// Groesse des Hauptspeichers (kann über das BIOS abgefragt werden,
|
||||
// aber sehr umstaendlich, daher hier fest eingetragen
|
||||
total_mem = MEM_SIZE_DEF;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* Nachfolgend sind die Operatoren von C++, die wir hier ueberschreiben *
|
||||
* und entsprechend 'mm_alloc' und 'mm_free' aufrufen. *
|
||||
*****************************************************************************/
|
||||
void* operator new(std::size_t size) {
|
||||
return allocator.alloc(size);
|
||||
}
|
||||
|
||||
void* operator new[](std::size_t count) {
|
||||
return allocator.alloc(count);
|
||||
}
|
||||
|
||||
void operator delete(void* ptr) {
|
||||
allocator.free(ptr);
|
||||
}
|
||||
|
||||
void operator delete[](void* ptr) {
|
||||
allocator.free(ptr);
|
||||
}
|
||||
|
||||
void operator delete(void* ptr, unsigned int sz) {
|
||||
allocator.free(ptr);
|
||||
}
|
||||
|
||||
// I don't know if accidentally deleted it but one delete was missing
|
||||
// https://en.cppreference.com/w/cpp/memory/new/operator_delete
|
||||
|
||||
void operator delete[](void* ptr, unsigned int sz) {
|
||||
allocator.free(ptr);
|
||||
}
|
58
src/kernel/memory/Allocator.h
Executable file
58
src/kernel/memory/Allocator.h
Executable file
@ -0,0 +1,58 @@
|
||||
/*****************************************************************************
|
||||
* *
|
||||
* A L L O C A T O R *
|
||||
* *
|
||||
*---------------------------------------------------------------------------*
|
||||
* Beschreibung: Einfache Speicherverwaltung. 'new' und 'delete' werden *
|
||||
* durch Ueberladen der entsprechenden Operatoren *
|
||||
* realisiert. *
|
||||
* *
|
||||
* Memory-Laylout *
|
||||
* *
|
||||
* boot.asm *
|
||||
* 0x07c0: Bootsector vom BIOS geladen *
|
||||
* 0x0060: Boot-Code verschiebt sich hier hin *
|
||||
* 0x9000: Setup-Code (max. 64K inkl. Stack) vom *
|
||||
* Bootsector-Code geladen *
|
||||
* setup.asm *
|
||||
* 0x1000: System-Code (max. 512K) geladen *
|
||||
* System-Code *
|
||||
* 0x100000: System-Code, kopiert nach Umschalten in *
|
||||
* den Protected Mode kopiert (GRUB kann nur *
|
||||
* an Adressen >1M laden) *
|
||||
* Globale Variablen: Direkt nach dem Code liegen die globalen *
|
||||
* Variablen. *
|
||||
* Heap: *
|
||||
* 0x300000: Start-Adresse der Heap-Verwaltung *
|
||||
* 0x400000: Letzte Adresse des Heaps *
|
||||
* *
|
||||
* Achtung: Benötigt einen PC mit mindestens 4 MB RAM! *
|
||||
* *
|
||||
* Autor: Michael Schoettner, HHU, 13.6.2020 *
|
||||
*****************************************************************************/
|
||||
#ifndef Allocator_include__
|
||||
#define Allocator_include__
|
||||
|
||||
constexpr const unsigned int BASIC_ALIGN = 4; // 32 Bit so 4 Bytes?
|
||||
constexpr const unsigned int HEAP_MIN_FREE_BLOCK_SIZE = 64; // min. Groesse eines freien Blocks
|
||||
|
||||
class Allocator {
|
||||
public:
|
||||
Allocator(Allocator& copy) = delete; // Verhindere Kopieren
|
||||
|
||||
Allocator();
|
||||
|
||||
// virtual ~Allocator() = default;
|
||||
|
||||
unsigned int heap_start;
|
||||
unsigned int heap_end;
|
||||
unsigned int heap_size;
|
||||
unsigned int initialized;
|
||||
|
||||
virtual void init() = 0;
|
||||
virtual void dump_free_memory() = 0;
|
||||
virtual void* alloc(unsigned int req_size) = 0;
|
||||
virtual void free(void* ptr) = 0;
|
||||
};
|
||||
|
||||
#endif
|
76
src/kernel/memory/BumpAllocator.cc
Executable file
76
src/kernel/memory/BumpAllocator.cc
Executable file
@ -0,0 +1,76 @@
|
||||
/*****************************************************************************
|
||||
* *
|
||||
* B U M P A L L O C A T O R *
|
||||
* *
|
||||
*---------------------------------------------------------------------------*
|
||||
* Beschreibung: Eine sehr einfache Heap-Verwaltung, welche freigegebenen *
|
||||
* Speicher nicht mehr nutzen kann. *
|
||||
* *
|
||||
* Autor: Michael Schoettner, HHU, 3.3.2022 *
|
||||
*****************************************************************************/
|
||||
|
||||
#include "BumpAllocator.h"
|
||||
#include "kernel/system/Globals.h"
|
||||
|
||||
/*****************************************************************************
|
||||
* Methode: BumpAllocator::init *
|
||||
*---------------------------------------------------------------------------*
|
||||
* Beschreibung: BumpAllokartor intitialisieren. *
|
||||
*****************************************************************************/
|
||||
void BumpAllocator::init() {
|
||||
|
||||
/* Hier muess Code eingefuegt werden */
|
||||
|
||||
allocations = 0;
|
||||
next = reinterpret_cast<unsigned char*>(heap_start);
|
||||
|
||||
log.info() << "Initialized Bump Allocator" << endl;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* Methode: BumpAllocator::dump_free_memory *
|
||||
*---------------------------------------------------------------------------*
|
||||
* Beschreibung: Ausgabe der Freispeicherinfos. Zu Debuggingzwecken. *
|
||||
*****************************************************************************/
|
||||
void BumpAllocator::dump_free_memory() {
|
||||
|
||||
/* Hier muess Code eingefuegt werden */
|
||||
|
||||
kout << "Freier Speicher:" << endl
|
||||
<< " - Next: " << hex << reinterpret_cast<unsigned int>(next)
|
||||
<< ", Allocations: " << dec << allocations << endl;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* Methode: BumpAllocator::alloc *
|
||||
*---------------------------------------------------------------------------*
|
||||
* Beschreibung: Einen neuen Speicherblock allozieren. *
|
||||
*****************************************************************************/
|
||||
void* BumpAllocator::alloc(unsigned int req_size) {
|
||||
|
||||
/* Hier muess Code eingefuegt werden */
|
||||
|
||||
log.debug() << "Requested " << hex << req_size << " Bytes" << endl;
|
||||
|
||||
if (req_size + reinterpret_cast<unsigned int>(next) > heap_end) {
|
||||
log.error() << " - More memory requested than available :(" << endl;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void* allocated = next;
|
||||
next = reinterpret_cast<unsigned char*>(reinterpret_cast<unsigned int>(next) + req_size);
|
||||
allocations = allocations + 1;
|
||||
|
||||
log.trace() << " - Allocated " << hex << req_size << " Bytes." << endl;
|
||||
|
||||
return allocated;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* Methode: BumpAllocator::free *
|
||||
*---------------------------------------------------------------------------*
|
||||
* Beschreibung: Nicht implementiert. *
|
||||
*****************************************************************************/
|
||||
void BumpAllocator::free(void* ptr) {
|
||||
log.error() << " mm_free: ptr= " << hex << reinterpret_cast<unsigned int>(ptr) << ", not supported" << endl;
|
||||
}
|
38
src/kernel/memory/BumpAllocator.h
Executable file
38
src/kernel/memory/BumpAllocator.h
Executable file
@ -0,0 +1,38 @@
|
||||
/*****************************************************************************
|
||||
* *
|
||||
* B U M P A L L O C A T O R *
|
||||
* *
|
||||
*---------------------------------------------------------------------------*
|
||||
* Beschreibung: Eine sehr einfache Heap-Verwaltung, welche freigegebenen *
|
||||
* Speicher nicht mehr nutzen kann. *
|
||||
* *
|
||||
* Autor: Michael Schoettner, HHU, 3.3.2022 *
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef BumpAllocator_include__
|
||||
#define BumpAllocator_include__
|
||||
|
||||
#include "Allocator.h"
|
||||
#include "kernel/log/Logger.h"
|
||||
|
||||
class BumpAllocator : Allocator {
|
||||
private:
|
||||
unsigned char* next;
|
||||
unsigned int allocations;
|
||||
|
||||
NamedLogger log;
|
||||
|
||||
public:
|
||||
BumpAllocator(Allocator& copy) = delete; // Verhindere Kopieren
|
||||
|
||||
BumpAllocator() : log("BMP-Alloc") {}; // Allocator() called implicitely in C++
|
||||
|
||||
// ~BumpAllocator() override = default;
|
||||
|
||||
void init() override;
|
||||
void dump_free_memory() override;
|
||||
void* alloc(unsigned int req_size) override;
|
||||
void free(void* ptr) override;
|
||||
};
|
||||
|
||||
#endif
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user