Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b6e583d41c |
No files matched your search
@@ -1,54 +0,0 @@
|
||||
# =============================================================================
|
||||
# Apps
|
||||
# User-facing applications, games, multimedia, UI and desktop resources
|
||||
# =============================================================================
|
||||
|
||||
^programs/(cmm|demos|emulator|games|media|other)/.* @KolibriOS/apps
|
||||
^contrib/(games|media|other)/.* @KolibriOS/apps
|
||||
^skins/.* @KolibriOS/apps
|
||||
|
||||
|
||||
# =============================================================================
|
||||
# System
|
||||
# Kernel, drivers, filesystems, SDK, libraries, toolchain and system utilities
|
||||
# =============================================================================
|
||||
|
||||
^kernel/.* @KolibriOS/system
|
||||
^drivers/.* @KolibriOS/system
|
||||
|
||||
^programs/(bcc32|develop|fs|hd_load|system|testing)/.* @KolibriOS/system
|
||||
^contrib/(C_Layer|sdk|toolchain)/.* @KolibriOS/system
|
||||
|
||||
# Shared system/API includes in programs/
|
||||
^programs/[^/]+\\.inc$ @KolibriOS/system
|
||||
|
||||
|
||||
# =============================================================================
|
||||
# Network
|
||||
# Network stack, network drivers, protocols, libraries and network applications
|
||||
# =============================================================================
|
||||
|
||||
^kernel/trunk/network/.* @KolibriOS/network
|
||||
|
||||
^drivers/ethernet/.* @KolibriOS/network
|
||||
^drivers/(mii|netdrv)\\.inc$ @KolibriOS/network
|
||||
|
||||
^programs/network/.* @KolibriOS/network
|
||||
^programs/network\\.inc$ @KolibriOS/network
|
||||
|
||||
^programs/develop/libraries/(http|network|kos_mbedtls)/.* @KolibriOS/network
|
||||
|
||||
^contrib/network/.* @KolibriOS/network
|
||||
|
||||
|
||||
# =============================================================================
|
||||
# DevOps
|
||||
# CI/CD, repository infrastructure, build system and autobuild configuration
|
||||
# =============================================================================
|
||||
|
||||
^\\.gitea/.* @KolibriOS/devops
|
||||
^_tools/.* @KolibriOS/devops
|
||||
|
||||
^\\.gitmodules$ @KolibriOS/devops
|
||||
^build\\.txt$ @KolibriOS/devops
|
||||
^tup\\.config\\.template$ @KolibriOS/devops
|
||||
@@ -19,38 +19,3 @@
|
||||
owner: "{{ storage_user }}"
|
||||
group: "{{ storage_user }}"
|
||||
mode: preserve
|
||||
|
||||
# per-program binaries browsable at <version>/<lang>/data/, like on the old builds server
|
||||
- name: Creating build tree folders
|
||||
ansible.builtin.file:
|
||||
path: "{{ storage_path }}/{{ version }}/{{ item | basename | regex_replace('\\.tar\\.gz$', '') }}/data"
|
||||
state: directory
|
||||
owner: "{{ storage_user }}"
|
||||
group: "{{ storage_user }}"
|
||||
mode: '0755'
|
||||
with_fileglob: "{{ tree_artifact_path }}/*.tar.gz"
|
||||
|
||||
- name: Unpacking build trees
|
||||
ansible.builtin.unarchive:
|
||||
src: "{{ item }}"
|
||||
dest: "{{ storage_path }}/{{ version }}/{{ item | basename | regex_replace('\\.tar\\.gz$', '') }}/data"
|
||||
owner: "{{ storage_user }}"
|
||||
group: "{{ storage_user }}"
|
||||
with_fileglob: "{{ tree_artifact_path }}/*.tar.gz"
|
||||
|
||||
# stable URL for the newest build: <storage_path>/latest/<lang>/...
|
||||
- name: Updating latest symlink
|
||||
ansible.builtin.file:
|
||||
src: "{{ version }}"
|
||||
dest: "{{ storage_path }}/latest"
|
||||
state: link
|
||||
force: true
|
||||
owner: "{{ storage_user }}"
|
||||
group: "{{ storage_user }}"
|
||||
|
||||
# emulators hardcode <site root>/<lang>/data/data/kolibri.img; storage_path is the ci folder, one level under the site root
|
||||
- name: Sending bare images to stable emulator paths
|
||||
ansible.builtin.copy:
|
||||
src: "{{ stable_artifact_path }}/"
|
||||
dest: "{{ storage_path }}/../"
|
||||
mode: preserve
|
||||
+22
-83
@@ -162,13 +162,12 @@ jobs:
|
||||
tup init
|
||||
tup variant ${{ matrix.lang }}.config
|
||||
|
||||
# build the image for language variant; keep the tup log for publishing
|
||||
# build the image for language variant
|
||||
- name: Build KolibriOS
|
||||
run: |
|
||||
set -o pipefail
|
||||
export PATH=/home/autobuild/tools/win32/bin:$PATH
|
||||
source kos32-export-env-vars ${{ gitea.workspace }}
|
||||
tup build-${{ matrix.lang }} 2>&1 | tee build.log
|
||||
tup build-${{ matrix.lang }}
|
||||
|
||||
# stamp the cache with its commit so later builds diff against it
|
||||
- name: Record cache base commit
|
||||
@@ -182,26 +181,15 @@ jobs:
|
||||
id: vars
|
||||
run: echo "descr=$(git describe --tags)" >> $GITEA_OUTPUT
|
||||
|
||||
# stage build outputs under their final names, plus distribution kit and checksums
|
||||
- name: Prepare artifacts
|
||||
# rename build outputs to their final names so artifacts are bare files
|
||||
- name: Rename images
|
||||
run: |
|
||||
set -e
|
||||
BASE="kolibrios-${{ steps.vars.outputs.descr }}-${{ matrix.lang }}"
|
||||
for ext in img iso raw; do
|
||||
cp "build-${{ matrix.lang }}/data/kolibri.$ext" "$BASE.$ext"
|
||||
cp "build-${{ matrix.lang }}/data/kolibri.$ext" \
|
||||
"kolibrios-${{ steps.vars.outputs.descr }}-${{ matrix.lang }}.$ext"
|
||||
done
|
||||
# zip: distr targets Windows/DOS users, Explorer opens it natively
|
||||
(cd "build-${{ matrix.lang }}/data" && zip -r -9 -q "${{ gitea.workspace }}/$BASE.distr.zip" distribution_kit)
|
||||
# whole build tree for per-program downloads; the big images ship separately
|
||||
tar -C "build-${{ matrix.lang }}" \
|
||||
--exclude './data/kolibri.iso' \
|
||||
--exclude './data/kolibri.raw' \
|
||||
--exclude './data/distribution_kit' \
|
||||
-czf "$BASE.tree.tar.gz" .
|
||||
sha256sum "$BASE".img "$BASE".iso "$BASE".raw "$BASE".distr.zip > "$BASE.sha256sums.txt"
|
||||
mv build.log "$BASE.build.log"
|
||||
|
||||
# publish the images; longer retention for the floppy image
|
||||
#publish the three images; longer retention for the floppy image.
|
||||
- name: Upload floppy image
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
@@ -223,34 +211,6 @@ jobs:
|
||||
path: kolibrios-${{ steps.vars.outputs.descr }}-${{ matrix.lang }}.raw
|
||||
retention-days: 15
|
||||
|
||||
- name: Upload distribution kit
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: kolibrios-${{ steps.vars.outputs.descr }}-${{ matrix.lang }}.distr.zip
|
||||
path: kolibrios-${{ steps.vars.outputs.descr }}-${{ matrix.lang }}.distr.zip
|
||||
retention-days: 30
|
||||
|
||||
- name: Upload checksums
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: kolibrios-${{ steps.vars.outputs.descr }}-${{ matrix.lang }}.sha256sums.txt
|
||||
path: kolibrios-${{ steps.vars.outputs.descr }}-${{ matrix.lang }}.sha256sums.txt
|
||||
retention-days: 90
|
||||
|
||||
- name: Upload build log
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: kolibrios-${{ steps.vars.outputs.descr }}-${{ matrix.lang }}.build.log
|
||||
path: kolibrios-${{ steps.vars.outputs.descr }}-${{ matrix.lang }}.build.log
|
||||
retention-days: 90
|
||||
|
||||
- name: Upload build tree
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: kolibrios-${{ steps.vars.outputs.descr }}-${{ matrix.lang }}.tree.tar.gz
|
||||
path: kolibrios-${{ steps.vars.outputs.descr }}-${{ matrix.lang }}.tree.tar.gz
|
||||
retention-days: 15
|
||||
|
||||
deploy:
|
||||
name: "Publish Images"
|
||||
runs-on: ubuntu-latest
|
||||
@@ -275,50 +235,31 @@ jobs:
|
||||
run: |
|
||||
set -eu
|
||||
|
||||
rm -rf ./norm-artifacts ./stable-artifacts ./tree-artifacts
|
||||
mkdir -p ./norm-artifacts ./stable-artifacts ./tree-artifacts
|
||||
rm -rf ./norm-artifacts
|
||||
mkdir -p ./norm-artifacts
|
||||
|
||||
find ./artifacts -type f -name 'kolibrios-*' | while read -r file; do
|
||||
fname="$(basename "$file")" # kolibrios-<descr>-<lang>.<suffix>
|
||||
case "$fname" in
|
||||
*.tree.tar.gz) stem="${fname%.tree.tar.gz}";;
|
||||
*.distr.zip) stem="${fname%.distr.zip}";;
|
||||
*.sha256sums.txt) stem="${fname%.sha256sums.txt}";;
|
||||
*.build.log) stem="${fname%.build.log}";;
|
||||
*.img) stem="${fname%.img}";;
|
||||
*.iso) stem="${fname%.iso}";;
|
||||
*.raw) stem="${fname%.raw}";;
|
||||
*) continue;;
|
||||
esac
|
||||
lang="${stem##*-}" # <lang> has no dashes, <descr> may
|
||||
find ./artifacts -type f \( \
|
||||
-name 'kolibrios-*.img' -o \
|
||||
-name 'kolibrios-*.iso' -o \
|
||||
-name 'kolibrios-*.raw' \
|
||||
\) | while read -r file; do
|
||||
fname="$(basename "$file")" # kolibrios-<descr>-<lang>.<ext>
|
||||
name_without_ext="${fname%.*}"
|
||||
lang="${name_without_ext##*-}"
|
||||
|
||||
mkdir -p "./norm-artifacts/$lang"
|
||||
case "$fname" in
|
||||
*.tree.tar.gz)
|
||||
# unpacked on the server into <version>/<lang>/data/ for per-program downloads
|
||||
cp "$file" "./tree-artifacts/$lang.tar.gz";;
|
||||
*.sha256sums.txt)
|
||||
cp "$file" "./norm-artifacts/$lang/sha256sums.txt";;
|
||||
*.build.log)
|
||||
cp "$file" "./norm-artifacts/$lang/build.log";;
|
||||
*.img)
|
||||
cp "$file" "./norm-artifacts/$lang/$fname"
|
||||
# emulators (e.g. v86) hardcode <lang>/data/data/kolibri.img at the site root
|
||||
mkdir -p "./stable-artifacts/$lang/data/data"
|
||||
cp "$file" "./stable-artifacts/$lang/data/data/kolibri.img";;
|
||||
*)
|
||||
cp "$file" "./norm-artifacts/$lang/$fname";;
|
||||
esac
|
||||
cp "$file" "./norm-artifacts/$lang/$fname"
|
||||
done
|
||||
|
||||
# derive the version (git describe) from an artifact name: kolibrios-<descr>-<lang>.iso -> <descr>
|
||||
sample="$(find ./norm-artifacts -type f -name 'kolibrios-*.iso' | head -n1)"
|
||||
# derive the version (git describe) from an artifact name:
|
||||
# kolibrios-<descr>-<lang>.<ext> -> <descr>
|
||||
sample="$(find ./norm-artifacts -type f -name 'kolibrios-*' | head -n1)"
|
||||
base="$(basename "${sample%.*}")" # kolibrios-<descr>-<lang>
|
||||
version="${base%-*}" # kolibrios-<descr>
|
||||
version="${version#kolibrios-}" # <descr>
|
||||
echo "version=$version" >> $GITEA_OUTPUT
|
||||
|
||||
find ./norm-artifacts ./stable-artifacts ./tree-artifacts -type f -print
|
||||
find ./norm-artifacts -type f -print
|
||||
|
||||
- name: Setup SSH
|
||||
run: |
|
||||
@@ -344,6 +285,4 @@ jobs:
|
||||
-e "storage_path=${{ secrets.STORAGE_PATH }}" \
|
||||
-e "version=${{ steps.normalize.outputs.version }}" \
|
||||
-e "artifact_path=${{ gitea.workspace }}/norm-artifacts" \
|
||||
-e "stable_artifact_path=${{ gitea.workspace }}/stable-artifacts" \
|
||||
-e "tree_artifact_path=${{ gitea.workspace }}/tree-artifacts" \
|
||||
-v
|
||||
@@ -34,10 +34,11 @@ jobs:
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: true
|
||||
token: ${{ secrets.BOT_TOKEN }}
|
||||
|
||||
- name: Bump ${{ matrix.name }} and open PR
|
||||
env:
|
||||
TOKEN: ${{ secrets.GITEA_TOKEN }}
|
||||
TOKEN: ${{ secrets.BOT_TOKEN }}
|
||||
API: ${{ github.api_url }}
|
||||
REPO: ${{ github.repository }}
|
||||
NAME: ${{ matrix.name }}
|
||||
|
||||
+1
-1
@@ -4,7 +4,7 @@
|
||||
branch = main
|
||||
[submodule "programs/develop/oberon07"]
|
||||
path = programs/develop/oberon07
|
||||
url = https://git.kolibrios.org/KolibriOS/oberon-07-compiler.git
|
||||
url = https://github.com/AntKrotov/oberon-07-compiler.git
|
||||
branch = master
|
||||
[submodule "programs/cmm"]
|
||||
path = programs/cmm
|
||||
|
||||
+5
-12
@@ -74,6 +74,7 @@ if build_type == "ru_RU" then tup.append_table(img_files, {
|
||||
{"WELCOME.HTM", VAR_DATA .. "/" .. build_type .. "/welcome.htm.kpack"},
|
||||
{"EXAMPLE.ASM", SRC_PROGS .. "/develop/examples/example/rus/example.asm"},
|
||||
{"DEVELOP/BACKY", SRC_PROGS .. "/develop/backy/Backy_ru"},
|
||||
{"GAMES/BASEKURS.KLA", build_type .. "/games/basekurs.kla"},
|
||||
{"File Managers/KFAR.INI", build_type .. "/File Managers/kfar.ini"},
|
||||
{"GAMES/DESCENT", build_type .. "/games/descent"},
|
||||
{"SETTINGS/.shell", SRC_PROGS .. "/system/shell/bin/rus/.shell"},
|
||||
@@ -191,12 +192,6 @@ extra_files = {
|
||||
{"kolibrios/develop/tcc/samples/", SRC_PROGS .. "/develop/ktcc/libc.obj/samples/*.sh"},
|
||||
{"kolibrios/develop/tcc/samples/clayer/", SRC_PROGS .. "/develop/ktcc/libc.obj/samples/clayer/*"},
|
||||
{"kolibrios/develop/utils/SPEDump", SRC_PROGS .. "/develop/SPEDump/SPEDump.kex"},
|
||||
{"kolibrios/develop/XDPascal/", SRC_PROGS .. "/develop/XDPascal/xdpk/*"},
|
||||
{"kolibrios/develop/XDPascal/projects2025/", SRC_PROGS .. "/develop/XDPascal/xdpk/projects2025/*"},
|
||||
{"kolibrios/develop/XDPascal/projects2025/Compiler/", SRC_PROGS .. "/develop/XDPascal/xdpk/projects2025/Compiler/*"},
|
||||
{"kolibrios/develop/XDPascal/projects2026/", SRC_PROGS .. "/develop/XDPascal/xdpk/projects2026/*"},
|
||||
{"kolibrios/develop/XDPascal/source/", SRC_PROGS .. "/develop/XDPascal/xdpk/source/*"},
|
||||
{"kolibrios/develop/XDPascal/units/", SRC_PROGS .. "/develop/XDPascal/xdpk/units/*"},
|
||||
{"kolibrios/emul/", "common/emul/*"},
|
||||
{"kolibrios/emul/dosbox/", "common/emul/DosBox/*"},
|
||||
{"kolibrios/emul/e80/readme.txt", SRC_PROGS .. "/emulator/e80/readme.txt"},
|
||||
@@ -296,6 +291,8 @@ extra_files = {
|
||||
{"kolibrios/utils/vmode", "common/vmode"},
|
||||
{"kolibrios/utils/texture", "common/utils/texture"},
|
||||
{"kolibrios/utils/kterm/kterm", VAR_PROGS .. "/other/kterm/kterm"},
|
||||
{"kolibrios/utils/kterm/serial.sys", VAR_DRVS .. "/serial/serial.sys"},
|
||||
{"kolibrios/utils/kterm/install.sh", SRC .. "/drivers/serial/install.sh"},
|
||||
{"kolibrios/utils/cnc_editor/cnc_editor", VAR_PROGS .. "/other/cnc_editor/cnc_editor"},
|
||||
{"kolibrios/utils/cnc_editor/kolibri.NC", SRC_PROGS .. "/other/cnc_editor/kolibri.NC"},
|
||||
{"kolibrios/utils/kfm/kfm.ini", "common/File Managers/kfm.ini"},
|
||||
@@ -542,7 +539,7 @@ tup.append_table(img_files, {
|
||||
{"NETWORK/PING", VAR_PROGS .. "/network/ping/ping"},
|
||||
{"NETWORK/NETCFG", VAR_PROGS .. "/network/netcfg/netcfg"},
|
||||
{"NETWORK/NETSTAT", VAR_PROGS .. "/network/netstat/netstat"},
|
||||
{"NETWORK/NETSURF", VAR_PROGS .. "/network/netsurf/netsurf"},
|
||||
{"NETWORK/NSINST", VAR_PROGS .. "/network/netsurf/nsinstall"},
|
||||
{"NETWORK/NSLOOKUP", VAR_PROGS .. "/network/nslookup/nslookup"},
|
||||
{"NETWORK/PASTA", VAR_PROGS .. "/network/pasta/pasta"},
|
||||
{"NETWORK/SYNERGYC", VAR_PROGS .. "/network/synergyc/synergyc"},
|
||||
@@ -573,15 +570,12 @@ tup.append_table(img_files, {
|
||||
{"DRIVERS/UHCI.SYS", VAR_DRVS .. "/usb/uhci.sys"},
|
||||
{"DRIVERS/OHCI.SYS", VAR_DRVS .. "/usb/ohci.sys"},
|
||||
{"DRIVERS/EHCI.SYS", VAR_DRVS .. "/usb/ehci.sys"},
|
||||
{"DRIVERS/XHCI.SYS", VAR_DRVS .. "/usb/xhci/xhci.sys"},
|
||||
{"DRIVERS/USBHID.SYS", VAR_DRVS .. "/usb/usbhid/usbhid.sys"},
|
||||
{"DRIVERS/USBFTDI.SYS", VAR_DRVS .. "/usb/usbftdi/usbftdi.sys"},
|
||||
{"DRIVERS/USBOTHER.SYS",VAR_DRVS .. "/usb/usbother/usbother.sys"},
|
||||
{"DRIVERS/USBCDC.SYS", VAR_DRVS .. "/usb/usbnet/usbcdc.sys"},
|
||||
{"DRIVERS/USBRNDIS.SYS", VAR_DRVS .. "/usb/usbnet/usbrndis.sys"},
|
||||
{"DRIVERS/USBSTOR.SYS", VAR_DRVS .. "/usb/usbstor.sys"},
|
||||
{"DRIVERS/RDC.SYS", VAR_DRVS .. "/video/rdc.sys"},
|
||||
{"DRIVERS/SERIAL.SYS", VAR_DRVS .. "/serial/serial.sys"},
|
||||
{"DRIVERS/COMMOUSE.SYS", VAR_DRVS .. "/mouse/commouse.sys"},
|
||||
{"DRIVERS/PS2MOUSE.SYS", VAR_DRVS .. "/mouse/ps2mouse4d/ps2mouse.sys"},
|
||||
{"DRIVERS/TMPDISK.SYS", VAR_DRVS .. "/disk/tmpdisk.sys"},
|
||||
@@ -655,6 +649,7 @@ tup.append_table(extra_files, {
|
||||
})
|
||||
-- For russian build, add russian-only programs.
|
||||
if build_type == "ru_RU" then tup.append_table(img_files, {
|
||||
{"GAMES/KLAVISHA", VAR_PROGS .. "/games/klavisha/klavisha"},
|
||||
{"DEVELOP/EXAMPLES/TESTCON2", VAR_PROGS .. "/develop/libraries/console_coff/examples/testcon2_rus"},
|
||||
}) else tup.append_table(img_files, {
|
||||
{"DEVELOP/EXAMPLES/TESTCON2", VAR_PROGS .. "/develop/libraries/console_coff/examples/testcon2_eng"},
|
||||
@@ -663,8 +658,6 @@ if build_type == "ru_RU" then tup.append_table(img_files, {
|
||||
if build_type == "ru_RU" then tup.append_table(extra_files, {
|
||||
{"kolibrios/utils/period", VAR_PROGS .. "/other/period/period"},
|
||||
{"kolibrios/games/Dungeons/Dungeons", VAR_PROGS .. "/games/Dungeons/Dungeons"},
|
||||
{"kolibrios/games/klavisha/klavisha", VAR_PROGS .. "/games/klavisha/klavisha"},
|
||||
{"kolibrios/games/klavisha/basekurs.kla", "ru_RU/games/basekurs.kla"},
|
||||
}) end
|
||||
|
||||
end -- tup.getconfig('NO_FASM') ~= 'full'
|
||||
|
||||
@@ -48,7 +48,7 @@ mht=/sys/network/WebView
|
||||
docx=/sys/network/WebView
|
||||
url=/sys/network/WebView
|
||||
fb2=/sys/fb2read
|
||||
kla=/kolibrios/games/klavisha/klavisha
|
||||
kla=/sys/games/klavisha
|
||||
pdf=/kolibrios/media/updf
|
||||
avi=/kolibrios/media/fplay_run
|
||||
mpg=/kolibrios/media/fplay_run
|
||||
|
||||
Binary file not shown.
@@ -179,7 +179,7 @@ stl=/sys/3d/view3ds
|
||||
skn=/sys/skincfg
|
||||
dtp=/sys/skincfg
|
||||
lif=/kolibrios/demos/life2
|
||||
kla=/kolibrios/games/klavisha/klavisha
|
||||
kla=/sys/games/klavisha
|
||||
pdf=/kolibrios/media/updf
|
||||
|
||||
smc=/kolibrios/emul/zsnes/zsnes
|
||||
|
||||
@@ -39,7 +39,7 @@ Donkey=/kg/donkey
|
||||
Loderunner=/kg/LRL/LRL,41
|
||||
; 21days=/kg/21days,104 ;rus only
|
||||
BabyPainter=/kg/BabyPainter,87
|
||||
Klavisha=/kg/klavisha/klavisha,69
|
||||
Klavisha=games/klavisha,69
|
||||
Millioneer=/kg/WHOWTBAM/whowtbam,114
|
||||
StarTrek71=/kg/sstartrek/SStarTrek
|
||||
Descent=games/descent
|
||||
|
||||
@@ -243,7 +243,7 @@ x=204
|
||||
y=0
|
||||
[22]
|
||||
name=NETSURF
|
||||
path=/sys/NETWORK/NETSURF
|
||||
path=/sys/NETWORK/NSINST
|
||||
param=
|
||||
ico=125
|
||||
x=204
|
||||
|
||||
@@ -116,7 +116,6 @@
|
||||
33 HTTPGet |network/httpget
|
||||
33 Downloader |network/dl
|
||||
12 WebView Browser |network/webview
|
||||
12 NetSurf |network/netsurf
|
||||
#13 **** SERVERS
|
||||
24 FTP |network/ftpd
|
||||
#14 **** OTHER
|
||||
|
||||
@@ -243,7 +243,7 @@ x=204
|
||||
y=0
|
||||
[22]
|
||||
name=NETSURF
|
||||
path=/sys/NETWORK/NETSURF
|
||||
path=/sys/NETWORK/NSINST
|
||||
param=
|
||||
ico=125
|
||||
x=204
|
||||
|
||||
@@ -121,7 +121,6 @@
|
||||
16 HTTPGet |network/httpget
|
||||
16 Descargas |network/dl
|
||||
16 Navegador WebView |network/webview
|
||||
12 NetSurf |network/netsurf
|
||||
#15 **** OTROS
|
||||
16 Reloj analвgico |demos/aclock
|
||||
16 Reloj binario |demos/bcdclk
|
||||
|
||||
@@ -39,7 +39,7 @@ docx=/sys/network/WebView
|
||||
url=/sys/network/WebView
|
||||
fb2=/sys/fb2read
|
||||
mht=/sys/network/WebView
|
||||
kla=/kolibrios/games/klavisha/klavisha
|
||||
kla=/sys/games/klavisha
|
||||
pdf=/kolibrios/media/updf
|
||||
avi=/kolibrios/media/fplay_run
|
||||
mpg=/kolibrios/media/fplay_run
|
||||
|
||||
@@ -39,7 +39,7 @@ Donkey=/kg/donkey
|
||||
Loderunner=/kg/LRL/LRL,41
|
||||
21days=/kg/21days,104 ;rus only
|
||||
BabyPainter=/kg/BabyPainter,87
|
||||
Klavisha=/kg/klavisha/klavisha,69
|
||||
Klavisha=games/klavisha,69
|
||||
Millioneer=/kg/WHOWTBAM/whowtbam,114
|
||||
StarTrek71=/kg/sstartrek/SStarTrek
|
||||
Descent=games/descent
|
||||
|
||||
@@ -243,7 +243,7 @@ x=204
|
||||
y=0
|
||||
[22]
|
||||
name=NETSURF
|
||||
path=/sys/NETWORK/NETSURF
|
||||
path=/sys/NETWORK/NSINST
|
||||
param=
|
||||
ico=125
|
||||
x=204
|
||||
|
||||
@@ -115,7 +115,6 @@
|
||||
33 HTTPGet |network/httpget
|
||||
33 Загрузчик |network/dl
|
||||
12 Браузер WebView |network/webview
|
||||
12 Браузер NetSurf |network/netsurf
|
||||
#14 **** Разное
|
||||
00 Эмуляторы* > |@6
|
||||
45 Создание скриншотов |scrshoot
|
||||
@@ -123,7 +122,7 @@
|
||||
18 FB2 Читалка |fb2read
|
||||
16 Аналоговые часы |aclock
|
||||
21 Таблица Менделеева |/kolibrios/utils/period
|
||||
59 Тренажёр KJIABuIIIA |/kolibrios/games/klavisha/klavisha
|
||||
59 Тренажёр KJ|ABuIIIA |games/klavisha
|
||||
16 Бинарные часы |demos/bcdclk
|
||||
53 Таймер |timer
|
||||
09 Разархиватор Unz |unz
|
||||
|
||||
@@ -515,18 +515,20 @@ HDA_AMP_VOLMASK equ 0x7F
|
||||
|
||||
|
||||
; unsolicited event handler
|
||||
HDA_UNSOL_QUEUE_SIZE equ 64 ; must stay a power of 2 (used as a bitmask for wrap)
|
||||
HDA_UNSOL_QUEUE_SIZE equ 64
|
||||
|
||||
struc HDA_BUS_UNSOLICITED
|
||||
{
|
||||
; ring buffer
|
||||
.queue rd HDA_UNSOL_QUEUE_SIZE * 2 ; 2 dword for each event (res and res_ex)
|
||||
.rp dd ? ; Read pointer
|
||||
.wp dd ? ; Write pointer
|
||||
; ; workqueue
|
||||
; .work dd ? ;struct work_struct work;
|
||||
; .bus dd ? ;struct hda_bus ;bus
|
||||
}
|
||||
;struc HDA_BUS_UNSOLICITED
|
||||
;{
|
||||
; ; ring buffer
|
||||
; .queue:
|
||||
; times HDA_UNSOL_QUEUE_SIZE*2 dd ?
|
||||
; .rp dd ?
|
||||
; .wp dd ?
|
||||
;
|
||||
; ; workqueue
|
||||
; .work dd ?;struct work_struct work;
|
||||
; .bus dd ? ;struct hda_bus ;bus
|
||||
;};
|
||||
|
||||
; Helper for automatic ping configuration
|
||||
AUTO_PIN_MIC equ 0
|
||||
|
||||
@@ -654,15 +654,7 @@ end if
|
||||
stdcall hda_codec_setup_stream, eax, SDO_TAG, 0, 0x11 ; Left & Right channels (Back panel)
|
||||
;Asper+ ]
|
||||
|
||||
if USE_UNSOL_EV = 0
|
||||
invoke TimerHS, 1, 0, snd_hda_automute, 1
|
||||
else
|
||||
; Keep the unsolicited-event mode on the event-driven path. Running
|
||||
; snd_hda_automute at startup can issue codec commands before the new
|
||||
; unsolicited-response flow is ready, which hangs some systems.
|
||||
invoke TimerHS, 1, 0, process_unsol_events, 0
|
||||
end if
|
||||
|
||||
invoke TimerHS, 1, 0, snd_hda_automute, 0
|
||||
if USE_SINGLE_MODE
|
||||
mov esi, msgSingleMode
|
||||
invoke SysMsgBoardStr
|
||||
@@ -2643,7 +2635,7 @@ proc snd_hda_automute stdcall, data:dword
|
||||
test eax, eax
|
||||
jz .out
|
||||
|
||||
stdcall snd_hda_read_pin_sense, edx, [data]
|
||||
stdcall snd_hda_read_pin_sense, edx, 1
|
||||
test eax, AC_PINSENSE_PRESENCE
|
||||
jnz @f
|
||||
xchg ecx, esi
|
||||
@@ -2672,64 +2664,24 @@ proc snd_hda_automute stdcall, data:dword
|
||||
endp
|
||||
|
||||
|
||||
; ;Asper remember to add this functions:
|
||||
; proc snd_hda_queue_unsol_event stdcall, par1:dword, par2:dword
|
||||
; ;if DEBUG
|
||||
; ; push esi
|
||||
; ; mov esi, msgUnsolEvent
|
||||
; ; invoke SysMsgBoardStr
|
||||
; ; pop esi
|
||||
; ;end if
|
||||
; if USE_UNSOL_EV = 1
|
||||
; ;Test. Do not make queue, process immediately!
|
||||
; ;stdcall here snd_hda_read_pin_sense stdcall, nid:dword, trigger_sense:dword
|
||||
; ;and then mute/unmute pin based on the results
|
||||
; invoke TimerHS, 1, 0, snd_hda_automute, 0
|
||||
; end if
|
||||
; ret
|
||||
; endp
|
||||
; ;...
|
||||
|
||||
align 4
|
||||
proc snd_hda_queue_unsol_event stdcall, res:dword, res_ex:dword
|
||||
; Single-producer (HDA IRQ) lock-free enqueue. The caller azx_update_rirb
|
||||
; only carries EBX across iterations and reloads the rest, and TimerHS
|
||||
; preserves EBX too - so by using scratch regs only we need no saves.
|
||||
mov eax, [unsol_events.wp]
|
||||
lea edx, [eax+1]
|
||||
and edx, HDA_UNSOL_QUEUE_SIZE - 1 ; next write pos (size must be 2^n)
|
||||
cmp edx, [unsol_events.rp]
|
||||
je .full ; ring full -> drop, keep 1 slot free
|
||||
|
||||
mov ecx, [res]
|
||||
mov [unsol_events.queue + eax*8], ecx
|
||||
mov ecx, [res_ex]
|
||||
mov [unsol_events.queue + eax*8 + 4], ecx
|
||||
mov [unsol_events.wp], edx ; publish only after data is stored
|
||||
|
||||
invoke TimerHS, 1, 0, process_unsol_events, 0
|
||||
.full:
|
||||
ret
|
||||
;Asper remember to add this functions:
|
||||
proc snd_hda_queue_unsol_event stdcall, par1:dword, par2:dword
|
||||
;if DEBUG
|
||||
; push esi
|
||||
; mov esi, msgUnsolEvent
|
||||
; invoke SysMsgBoardStr
|
||||
; pop esi
|
||||
;end if
|
||||
if USE_UNSOL_EV = 1
|
||||
;Test. Do not make queue, process immediately!
|
||||
;stdcall here snd_hda_read_pin_sense stdcall, nid:dword, trigger_sense:dword
|
||||
;and then mute/unmute pin based on the results
|
||||
invoke TimerHS, 1, 0, snd_hda_automute, 0
|
||||
end if
|
||||
ret
|
||||
endp
|
||||
;...
|
||||
|
||||
align 4
|
||||
proc process_unsol_events stdcall, data:dword
|
||||
; Runs from TimerHS (single consumer). Uses only EAX (scratch) and calls
|
||||
; snd_hda_automute, which preserves every register, so nothing is saved.
|
||||
.loop:
|
||||
mov eax, [unsol_events.rp]
|
||||
cmp eax, [unsol_events.wp]
|
||||
je .done
|
||||
; The event payload is at [unsol_events.queue + eax*8] (res) and +4 (res_ex).
|
||||
; Per-pin tag parsing is not implemented yet, so just re-evaluate jack state.
|
||||
inc eax
|
||||
and eax, HDA_UNSOL_QUEUE_SIZE - 1
|
||||
mov [unsol_events.rp], eax
|
||||
stdcall snd_hda_automute, 0
|
||||
jmp .loop
|
||||
.done:
|
||||
ret
|
||||
endp
|
||||
|
||||
align 4
|
||||
proc fdword2str stdcall, flags:dword ; bit 0 - skipLeadZeroes; bit 1 - newLine; other bits undefined
|
||||
@@ -3105,7 +3057,6 @@ aspinlock dd SPINLOCK_FREE
|
||||
|
||||
codec CODEC
|
||||
ctrl AC_CNTRL
|
||||
unsol_events HDA_BUS_UNSOLICITED
|
||||
|
||||
;Asper: BDL must be aligned to 128 according to HDA specification.
|
||||
pcmout_bdl rd 1
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
SERIAL_COMPATIBLE_API_VER = 1 ; increments in case of breaking changes
|
||||
SERIAL_COMPATIBLE_API_VER = 0 ; increments in case of breaking changes
|
||||
|
||||
SERIAL_API_GET_VERSION = 0
|
||||
SERIAL_API_SRV_ADD_PORT = 1
|
||||
@@ -9,7 +9,6 @@ SERIAL_API_CLOSE_PORT = 5
|
||||
SERIAL_API_SETUP_PORT = 6
|
||||
SERIAL_API_READ = 7
|
||||
SERIAL_API_WRITE = 8
|
||||
SERIAL_API_ENUM_PORTS = 9
|
||||
|
||||
SERIAL_API_ERR_PORT_INVALID = 1
|
||||
SERIAL_API_ERR_PORT_BUSY = 2
|
||||
@@ -30,9 +29,6 @@ SERIAL_CONF_STOP_BITS_2 = 2
|
||||
|
||||
SERIAL_CONF_FLOW_CTRL_NONE = 0
|
||||
|
||||
SERIAL_INFO_DRIVER_LEN = 16
|
||||
SERIAL_INFO_DESCR_LEN = 64
|
||||
|
||||
struct SP_DRIVER
|
||||
size dd ? ; size of this struct
|
||||
startup dd ? ; int __stdcall (*startup)(void *drv_data, const struct serial_conf *conf);
|
||||
@@ -50,20 +46,7 @@ struct SP_CONF
|
||||
flow_ctrl db ?
|
||||
ends
|
||||
|
||||
struct SP_PORT_INFO
|
||||
size dd ? ; size of this struct
|
||||
driver dd ? ; ASCIIZ driver name, e.g. "uart16550", "usb-cdc"
|
||||
descr dd ? ; ASCIIZ description, may be NULL
|
||||
ends
|
||||
|
||||
struct SP_PORT_ENUM_ENTRY
|
||||
id dd ? ; unique port number (SERIAL_PORT.id)
|
||||
busy dd ? ; 0 = free, non-zero = port is opened
|
||||
driver rb SERIAL_INFO_DRIVER_LEN
|
||||
descr rb SERIAL_INFO_DESCR_LEN
|
||||
ends
|
||||
|
||||
proc serial_add_port stdcall, drv:dword, drv_data:dword, info:dword
|
||||
proc serial_add_port stdcall, drv:dword, drv_data:dword
|
||||
locals
|
||||
handler dd ?
|
||||
io_code dd ?
|
||||
@@ -77,7 +60,7 @@ endl
|
||||
mov [io_code], SERIAL_API_SRV_ADD_PORT
|
||||
lea eax, [drv]
|
||||
mov [input], eax
|
||||
mov [inp_size], 12
|
||||
mov [inp_size], 8
|
||||
xor eax, eax
|
||||
mov [output], eax
|
||||
mov [out_size], eax
|
||||
@@ -146,7 +129,7 @@ proc serial_port_init
|
||||
ret
|
||||
endp
|
||||
|
||||
proc serial_port_get_version stdcall uses ebx, version:dword
|
||||
proc serial_port_get_version stdcall, version:dword
|
||||
locals
|
||||
.handler dd ?
|
||||
.io_code dd ?
|
||||
@@ -166,7 +149,7 @@ endl
|
||||
|
||||
lea ecx, [.handler]
|
||||
mcall SF_SYS_MISC, SSF_CONTROL_DRIVER
|
||||
|
||||
|
||||
ret
|
||||
endp
|
||||
|
||||
@@ -314,43 +297,6 @@ endl
|
||||
ret
|
||||
endp
|
||||
|
||||
proc serial_port_enum stdcall uses ebx, buf:dword, buf_size:dword, \
|
||||
total:dword, filled:dword
|
||||
locals
|
||||
.handler dd ?
|
||||
.io_code dd ?
|
||||
.input dd ?
|
||||
.inp_size dd ?
|
||||
.output dd ?
|
||||
.out_size dd ?
|
||||
endl
|
||||
push [buf_size]
|
||||
push [buf]
|
||||
mov eax, [serial_drv_handle]
|
||||
mov [.handler], eax
|
||||
mov dword [.io_code], SERIAL_API_ENUM_PORTS
|
||||
mov [.input], esp
|
||||
mov dword [.inp_size], 8
|
||||
sub esp, 8
|
||||
mov [.output], esp
|
||||
mov dword [.out_size], 8
|
||||
|
||||
lea ecx, [.handler]
|
||||
mcall SF_SYS_MISC, SSF_CONTROL_DRIVER
|
||||
|
||||
pop ebx edx
|
||||
cmp eax, -1
|
||||
je .err
|
||||
mov ecx, [total]
|
||||
mov [ecx], ebx
|
||||
mov ecx, [filled]
|
||||
mov [ecx], edx
|
||||
.err:
|
||||
|
||||
add esp, 8
|
||||
ret
|
||||
endp
|
||||
|
||||
align 4
|
||||
serial_drv_name db "SERIAL", 0
|
||||
serial_drv_handle dd ?
|
||||
@@ -0,0 +1,5 @@
|
||||
#SHS
|
||||
echo Installing serial driver for kterm...
|
||||
cp /kolibrios/utils/kterm/serial.sys /sys/drivers/
|
||||
/sys/loaddrv serial
|
||||
echo Serial driver successfully installed!
|
||||
+7
-148
@@ -44,8 +44,6 @@ struct SERIAL_PORT
|
||||
rx_buf RING_BUF
|
||||
tx_buf RING_BUF
|
||||
conf SP_CONF
|
||||
driver rb SERIAL_INFO_DRIVER_LEN ; ASCIIZ, copied from SP_PORT_INFO.driver in add_port
|
||||
descr rb SERIAL_INFO_DESCR_LEN ; ASCIIZ, copied from SP_PORT_INFO.descr in add_port (may be empty)
|
||||
ends
|
||||
|
||||
proc START c, reason:dword, cmdline:dword
|
||||
@@ -59,7 +57,7 @@ proc START c, reason:dword, cmdline:dword
|
||||
stdcall uart_probe, 0x2f8, 3
|
||||
stdcall uart_probe, 0x3e8, 4
|
||||
stdcall uart_probe, 0x2e8, 3
|
||||
invoke RegService, serial_drv_name, service_proc
|
||||
invoke RegService, drv_name, service_proc
|
||||
ret
|
||||
|
||||
.fail:
|
||||
@@ -77,7 +75,7 @@ srv_calls:
|
||||
dd service_proc.setup
|
||||
dd service_proc.read
|
||||
dd service_proc.write
|
||||
dd service_proc.enum_ports
|
||||
; TODO enumeration
|
||||
srv_calls_end:
|
||||
|
||||
proc service_proc stdcall uses ebx esi edi, ioctl:dword
|
||||
@@ -99,13 +97,11 @@ proc service_proc stdcall uses ebx esi edi, ioctl:dword
|
||||
; in:
|
||||
; +0: driver
|
||||
; +4: driver data
|
||||
; +8: port info (SP_PORT_INFO*)
|
||||
cmp [edx + IOCTL.inp_size], 12
|
||||
cmp [edx + IOCTL.inp_size], 8
|
||||
jb .err
|
||||
mov ebx, [edx + IOCTL.input]
|
||||
mov ecx, [ebx]
|
||||
mov edx, [ebx + 4]
|
||||
mov ebx, [ebx + 8]
|
||||
call add_port
|
||||
ret
|
||||
|
||||
@@ -141,7 +137,6 @@ proc service_proc stdcall uses ebx esi edi, ioctl:dword
|
||||
; +4 addr to SERIAL_CONF
|
||||
; out:
|
||||
; +0 port handle if success
|
||||
; eax = 0 if success, otherwise an error code SERIAL_API_ERR_*
|
||||
cmp [edx + IOCTL.inp_size], 8
|
||||
jb .err
|
||||
cmp [edx + IOCTL.out_size], 4
|
||||
@@ -225,60 +220,25 @@ proc service_proc stdcall uses ebx esi edi, ioctl:dword
|
||||
mov [ebx], ecx
|
||||
ret
|
||||
|
||||
.enum_ports:
|
||||
; in:
|
||||
; +0 output buffer (array of SP_PORT_ENUM_ENTRY), may be NULL
|
||||
; +4 output buffer size in bytes
|
||||
; out:
|
||||
; +0 total number of ports in the system
|
||||
; +4 number of entries actually filled into the buffer
|
||||
; eax = 0 if success, -1 otherwise
|
||||
cmp [edx + IOCTL.inp_size], 8
|
||||
jb .err
|
||||
cmp [edx + IOCTL.out_size], 8
|
||||
jb .err
|
||||
mov ebx, [edx + IOCTL.input]
|
||||
push edx
|
||||
mov eax, [ebx]
|
||||
mov edx, [ebx + 4]
|
||||
call sp_enum
|
||||
pop edx
|
||||
mov ebx, [edx + IOCTL.output]
|
||||
mov [ebx], eax
|
||||
mov [ebx + 4], ecx
|
||||
xor eax, eax
|
||||
ret
|
||||
|
||||
.err:
|
||||
or eax, -1
|
||||
ret
|
||||
endp
|
||||
|
||||
; struct SERIAL_PORT __fastcall *add_port(const struct SP_DRIVER *drv, const void *drv_data);
|
||||
align 4
|
||||
; @param ecx pointer to SP_DRIVER
|
||||
; @param edx driver-specific argument
|
||||
; @param ebx pointer to SP_PORT_INFO
|
||||
; @return SERIAL_PORT descriptor
|
||||
proc add_port uses edi
|
||||
DEBUGF L_DBG, "serial.sys: add port drv=%x drv_data=%x info=%x\n", ecx, edx, ebx
|
||||
DEBUGF L_DBG, "serial.sys: add port drv=%x drv_data=%x\n", ecx, edx
|
||||
|
||||
mov eax, [ecx + SP_DRIVER.size]
|
||||
cmp eax, sizeof.SP_DRIVER
|
||||
jne .fail
|
||||
|
||||
test ebx, ebx
|
||||
jz .fail
|
||||
mov eax, [ebx + SP_PORT_INFO.size]
|
||||
cmp eax, sizeof.SP_PORT_INFO
|
||||
jne .fail
|
||||
|
||||
; alloc memory for serial port descriptor
|
||||
push ecx
|
||||
push edx
|
||||
push ebx
|
||||
movi eax, sizeof.SERIAL_PORT
|
||||
invoke Kmalloc
|
||||
pop ebx
|
||||
pop edx
|
||||
pop ecx
|
||||
test eax, eax
|
||||
@@ -292,17 +252,6 @@ proc add_port uses edi
|
||||
invoke MutexInit
|
||||
and [edi + SERIAL_PORT.con], 0
|
||||
|
||||
; copy port info strings
|
||||
mov eax, [ebx + SP_PORT_INFO.driver]
|
||||
lea edx, [edi + SERIAL_PORT.driver]
|
||||
mov ecx, SERIAL_INFO_DRIVER_LEN
|
||||
call copy_bounded_str
|
||||
|
||||
mov eax, [ebx + SP_PORT_INFO.descr]
|
||||
lea edx, [edi + SERIAL_PORT.descr]
|
||||
mov ecx, SERIAL_INFO_DESCR_LEN
|
||||
call copy_bounded_str
|
||||
|
||||
mov ecx, port_list_mutex
|
||||
invoke MutexLock
|
||||
|
||||
@@ -333,35 +282,7 @@ proc add_port uses edi
|
||||
endp
|
||||
|
||||
align 4
|
||||
; copies an ASCIIZ string into a fixed-size buffer: copies up to (size - 1)
|
||||
; bytes or until the NUL, then zero-pads the rest of the buffer
|
||||
; @param eax source ASCIIZ ptr, may be NULL
|
||||
; @param edx dest buffer ptr
|
||||
; @param ecx dest buffer size in bytes, must be >= 1
|
||||
proc copy_bounded_str uses esi edi
|
||||
mov esi, eax
|
||||
mov edi, edx
|
||||
dec ecx ; reserve the last byte for the NUL terminator
|
||||
.copy:
|
||||
test ecx, ecx
|
||||
jz .pad
|
||||
test esi, esi
|
||||
jz .pad
|
||||
lodsb
|
||||
test al, al
|
||||
jz .pad
|
||||
stosb
|
||||
dec ecx
|
||||
jmp .copy
|
||||
.pad:
|
||||
inc ecx ; account for the reserved NUL byte
|
||||
xor al, al
|
||||
rep stosb
|
||||
ret
|
||||
endp
|
||||
|
||||
align 4
|
||||
; @param ecx serial port descriptor
|
||||
; u32 __fastcall *remove_port(struct SERIAL_PORT *port);
|
||||
proc remove_port uses esi
|
||||
mov esi, ecx
|
||||
mov ecx, port_list_mutex
|
||||
@@ -736,69 +657,7 @@ proc sp_write
|
||||
ret
|
||||
endp
|
||||
|
||||
align 4
|
||||
; @param eax buf
|
||||
; @param edx buf_size (bytes)
|
||||
; @return eax total port count in the system
|
||||
; ecx entries filled into buf
|
||||
proc sp_enum uses ebx esi edi
|
||||
mov ecx, eax
|
||||
mov eax, edx
|
||||
xor edx, edx
|
||||
mov ebx, sizeof.SP_PORT_ENUM_ENTRY
|
||||
div ebx
|
||||
; eax max entries count
|
||||
|
||||
mov edi, ecx
|
||||
imul eax, sizeof.SP_PORT_ENUM_ENTRY
|
||||
add eax, ecx
|
||||
mov edx, eax ; end-of-buffer boundary
|
||||
|
||||
xor ebx, ebx ; total port count
|
||||
xor ecx, ecx ; filled count
|
||||
|
||||
push ecx edx
|
||||
mov ecx, port_list_mutex
|
||||
invoke MutexLock
|
||||
pop edx ecx
|
||||
|
||||
mov esi, port_list
|
||||
.next:
|
||||
mov esi, [esi + SERIAL_PORT.fd]
|
||||
cmp esi, port_list
|
||||
jz .done
|
||||
inc ebx
|
||||
cmp edi, edx
|
||||
jae .next
|
||||
|
||||
mov eax, [esi + SERIAL_PORT.id]
|
||||
mov [edi + SP_PORT_ENUM_ENTRY.id], eax
|
||||
xor eax, eax
|
||||
cmp dword [esi + SERIAL_PORT.con], 0
|
||||
setnz al
|
||||
mov [edi + SP_PORT_ENUM_ENTRY.busy], eax
|
||||
|
||||
push ecx esi edi
|
||||
lea esi, [esi + SERIAL_PORT.driver]
|
||||
lea edi, [edi + SP_PORT_ENUM_ENTRY.driver]
|
||||
mov ecx, (SERIAL_INFO_DRIVER_LEN + SERIAL_INFO_DESCR_LEN) / 4
|
||||
rep movsd
|
||||
pop edi esi ecx
|
||||
|
||||
add edi, sizeof.SP_PORT_ENUM_ENTRY
|
||||
inc ecx
|
||||
jmp .next
|
||||
|
||||
.done:
|
||||
push ecx
|
||||
mov ecx, port_list_mutex
|
||||
invoke MutexUnlock
|
||||
pop ecx
|
||||
|
||||
mov eax, ebx
|
||||
ret
|
||||
endp
|
||||
|
||||
drv_name db 'SERIAL', 0
|
||||
include_debug_strings
|
||||
|
||||
align 4
|
||||
|
||||
@@ -169,7 +169,6 @@ proc uart_probe stdcall uses ebx esi edi, io_addr:dword, irqn:dword
|
||||
; register port
|
||||
lea ecx, [uart_drv]
|
||||
mov edx, edi
|
||||
lea ebx, [uart_port_info]
|
||||
call add_port
|
||||
test eax, eax
|
||||
jz .free_desc ; TODO detach_int_handler?
|
||||
@@ -407,11 +406,3 @@ uart_drv:
|
||||
dd uart_reconf
|
||||
dd uart_tx
|
||||
uart_drv_end:
|
||||
|
||||
align 4
|
||||
uart_port_info:
|
||||
dd uart_port_end - uart_port_info
|
||||
dd uart_port_name
|
||||
dd 0
|
||||
uart_port_end:
|
||||
uart_port_name db 'uart16550', 0
|
||||
+310
-203
@@ -1,6 +1,6 @@
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; ;;
|
||||
;; Copyright (C) KolibriOS team 2004-2026. All rights reserved. ;;
|
||||
;; Copyright (C) KolibriOS team 2004-2015. All rights reserved. ;;
|
||||
;; Distributed under terms of the GNU General Public License ;;
|
||||
;; ;;
|
||||
;; FTDI chips driver for KolibriOS ;;
|
||||
@@ -15,11 +15,10 @@
|
||||
format PE DLL native 0.05
|
||||
entry START
|
||||
|
||||
L_DBG = 1
|
||||
L_ERR = 2
|
||||
DEBUG = 1
|
||||
|
||||
__DEBUG__ = 1
|
||||
__DEBUG_LEVEL__ = L_ERR
|
||||
__DEBUG_LEVEL__ = 1
|
||||
|
||||
node equ ftdi_context
|
||||
node.next equ ftdi_context.next_context
|
||||
@@ -123,10 +122,9 @@ TYPE_232H=6
|
||||
TYPE_230X=7
|
||||
|
||||
;strings
|
||||
my_driver db 'usbftdi',0
|
||||
my_driver db 'usbother',0
|
||||
serial_driver db 'SERIAL',0
|
||||
nomemory_msg db 'ftdi: no memory',13,10,0
|
||||
ftdi_port_name db 'ftdi',0
|
||||
nomemory_msg db 'K : no memory',13,10,0
|
||||
|
||||
; Structures
|
||||
struct ftdi_context
|
||||
@@ -202,13 +200,10 @@ endp
|
||||
|
||||
|
||||
proc AddDevice stdcall uses ebx esi edi, .config_pipe:DWORD, .config_descr:DWORD, .interface:DWORD
|
||||
locals
|
||||
.pinfo rb sizeof.SP_PORT_INFO
|
||||
endl
|
||||
|
||||
|
||||
invoke USBGetParam, [.config_pipe], 0
|
||||
mov edx, eax
|
||||
DEBUGF L_DBG, 'ftdi: Detected device vendor: 0x%x\n', [eax+usb_descr.idVendor]
|
||||
DEBUGF 2,'K : Detected device vendor: 0x%x\n', [eax+usb_descr.idVendor]
|
||||
cmp word[eax+usb_descr.idVendor], 0x0403
|
||||
jnz .notftdi
|
||||
mov eax, sizeof.ftdi_context
|
||||
@@ -219,7 +214,7 @@ endl
|
||||
invoke SysMsgBoardStr
|
||||
jmp .nothing
|
||||
@@:
|
||||
DEBUGF L_DBG, 'ftdi: Adding struct to list 0x%x\n', eax
|
||||
DEBUGF 2,'K : Adding struct to list 0x%x\n', eax
|
||||
call linkedlist_add
|
||||
|
||||
mov ebx, [.config_pipe]
|
||||
@@ -238,7 +233,7 @@ endl
|
||||
jmp .slow
|
||||
|
||||
mov cx, [edx+usb_descr.bcdDevice]
|
||||
DEBUGF L_DBG, 'ftdi: Chip type 0x%x\n', ecx
|
||||
DEBUGF 2, 'K : Chip type 0x%x\n', ecx
|
||||
cmp cx, 0x400
|
||||
jnz @f
|
||||
mov [eax + ftdi_context.chipType], TYPE_BM
|
||||
@@ -292,13 +287,8 @@ endl
|
||||
mov eax, [serial_drv_entry]
|
||||
test eax, eax
|
||||
jz @f
|
||||
mov dword [.pinfo + SP_PORT_INFO.size], sizeof.SP_PORT_INFO
|
||||
mov dword [.pinfo + SP_PORT_INFO.driver], ftdi_port_name
|
||||
; TODO obtain iManufacturer, iProduct and iSerial strings
|
||||
mov dword [.pinfo + SP_PORT_INFO.descr], 0
|
||||
lea ecx, [.pinfo]
|
||||
stdcall serial_add_port, uart_drv, ebx, ecx
|
||||
DEBUGF L_DBG, 'ftdi: add serial port with result %x\n', eax
|
||||
stdcall serial_add_port, uart_drv, ebx
|
||||
DEBUGF 1, "usbftdi: add serial port with result %x\n", eax
|
||||
@@:
|
||||
mov [ebx + ftdi_context.port_handle], eax
|
||||
|
||||
@@ -306,7 +296,7 @@ endl
|
||||
ret
|
||||
|
||||
.notftdi:
|
||||
DEBUGF L_DBG, 'ftdi: Skipping not FTDI device\n'
|
||||
DEBUGF 1,'K : Skipping not FTDI device\n'
|
||||
.nothing:
|
||||
xor eax, eax
|
||||
ret
|
||||
@@ -327,7 +317,7 @@ EventData rd 3
|
||||
endl
|
||||
mov edi, [ioctl]
|
||||
mov eax, [edi+io_code]
|
||||
DEBUGF L_DBG, 'ftdi: FTDI got the request: %d\n', eax
|
||||
DEBUGF 1,'K : FTDI got the request: %d\n', eax
|
||||
test eax, eax ;0
|
||||
jz .version
|
||||
dec eax ;1
|
||||
@@ -426,7 +416,7 @@ endl
|
||||
.version:
|
||||
jmp .endswitch
|
||||
.error:
|
||||
DEBUGF L_ERR, 'ftdi: error occured! %d\n', eax
|
||||
DEBUGF 1, 'K : FTDI error occured! %d\n', eax
|
||||
;mov esi, [edi+output]
|
||||
;mov [esi], dword 'ERR0'
|
||||
;or [esi], eax
|
||||
@@ -459,7 +449,7 @@ endl
|
||||
mov word[ConfPacket+6], cx
|
||||
.own_index:
|
||||
mov ebx, [edi+4]
|
||||
DEBUGF L_DBG, 'ftdi: ConfPacket 0x%x 0x%x\n', [ConfPacket], [ConfPacket+4]
|
||||
DEBUGF 2,'K : ConfPacket 0x%x 0x%x\n', [ConfPacket], [ConfPacket+4]
|
||||
lea esi, [ConfPacket]
|
||||
lea edi, [EventData]
|
||||
invoke USBControlTransferAsync, [ebx + ftdi_context.nullP], esi, 0,\
|
||||
@@ -475,7 +465,7 @@ endl
|
||||
jmp .error
|
||||
|
||||
.ftdi_setrtshigh:
|
||||
DEBUGF L_DBG, 'ftdi: Setting RTS pin HIGH PID: %d Dev handler 0x0x%x\n', [edi],\
|
||||
DEBUGF 2,'K : FTDI Setting RTS pin HIGH PID: %d Dev handler 0x0x%x\n', [edi],\
|
||||
[edi+4]
|
||||
mov dword[ConfPacket], (FTDI_DEVICE_OUT_REQTYPE) \
|
||||
+ (SIO_SET_MODEM_CTRL_REQUEST shl 8) \
|
||||
@@ -483,7 +473,7 @@ endl
|
||||
jmp .ftdi_out_control_transfer_noinp
|
||||
|
||||
.ftdi_setrtslow:
|
||||
DEBUGF L_DBG, 'ftdi: Setting RTS pin LOW PID: %d Dev handler 0x0x%x\n', [edi],\
|
||||
DEBUGF 2,'K : FTDI Setting RTS pin LOW PID: %d Dev handler 0x0x%x\n', [edi],\
|
||||
[edi+4]
|
||||
mov dword[ConfPacket], (FTDI_DEVICE_OUT_REQTYPE) \
|
||||
+ (SIO_SET_MODEM_CTRL_REQUEST shl 8) \
|
||||
@@ -491,7 +481,7 @@ endl
|
||||
jmp .ftdi_out_control_transfer_noinp
|
||||
|
||||
.ftdi_setdtrhigh:
|
||||
DEBUGF L_DBG, 'ftdi: Setting DTR pin HIGH PID: %d Dev handler 0x0x%x\n', [edi],\
|
||||
DEBUGF 2,'K : FTDI Setting DTR pin HIGH PID: %d Dev handler 0x0x%x\n', [edi],\
|
||||
[edi+4]
|
||||
mov dword[ConfPacket], (FTDI_DEVICE_OUT_REQTYPE) \
|
||||
+ (SIO_SET_MODEM_CTRL_REQUEST shl 8) \
|
||||
@@ -499,7 +489,7 @@ endl
|
||||
jmp .ftdi_out_control_transfer_noinp
|
||||
|
||||
.ftdi_setdtrlow:
|
||||
DEBUGF L_DBG, 'ftdi: Setting DTR pin LOW PID: %d Dev handler 0x0x%x\n', [edi],\
|
||||
DEBUGF 2,'K : FTDI Setting DTR pin LOW PID: %d Dev handler 0x0x%x\n', [edi],\
|
||||
[edi+4]
|
||||
mov dword[ConfPacket], (FTDI_DEVICE_OUT_REQTYPE) \
|
||||
+ (SIO_SET_MODEM_CTRL_REQUEST shl 8) \
|
||||
@@ -507,7 +497,7 @@ endl
|
||||
jmp .ftdi_out_control_transfer_noinp
|
||||
|
||||
.ftdi_usb_reset:
|
||||
DEBUGF L_DBG, 'ftdi: Reseting PID: %d Dev handler 0x0x%x\n', [edi],\
|
||||
DEBUGF 2,'K : FTDI Reseting PID: %d Dev handler 0x0x%x\n', [edi],\
|
||||
[edi+4]
|
||||
mov dword[ConfPacket], (FTDI_DEVICE_OUT_REQTYPE) \
|
||||
+ (SIO_RESET_REQUEST shl 8) \
|
||||
@@ -515,7 +505,7 @@ endl
|
||||
jmp .ftdi_out_control_transfer_noinp
|
||||
|
||||
.ftdi_purge_rx_buf:
|
||||
DEBUGF L_DBG, 'ftdi: Purge TX buffer PID: %d Dev handler 0x0x%x\n', [edi],\
|
||||
DEBUGF 2, 'K : FTDI Purge TX buffer PID: %d Dev handler 0x0x%x\n', [edi],\
|
||||
[edi+4]
|
||||
mov dword[ConfPacket], (FTDI_DEVICE_OUT_REQTYPE) \
|
||||
+ (SIO_RESET_REQUEST shl 8) \
|
||||
@@ -523,7 +513,7 @@ endl
|
||||
jmp .ftdi_out_control_transfer_noinp
|
||||
|
||||
.ftdi_purge_tx_buf:
|
||||
DEBUGF L_DBG, 'ftdi: Purge RX buffer PID: %d Dev handler 0x0x%x\n', [edi],\
|
||||
DEBUGF 2, 'K : FTDI Purge RX buffer PID: %d Dev handler 0x0x%x\n', [edi],\
|
||||
[edi+4]
|
||||
mov dword[ConfPacket], (FTDI_DEVICE_OUT_REQTYPE) \
|
||||
+ (SIO_RESET_REQUEST shl 8) \
|
||||
@@ -531,42 +521,42 @@ endl
|
||||
jmp .ftdi_out_control_transfer_noinp
|
||||
|
||||
.ftdi_set_bitmode:
|
||||
DEBUGF L_DBG, 'ftdi: Set bitmode 0x%x, bitmask 0x%x %d PID: %d Dev handler 0x0x%x\n', \
|
||||
DEBUGF 2, 'K : FTDI Set bitmode 0x%x, bitmask 0x%x %d PID: %d Dev handler 0x0x%x\n', \
|
||||
[edi+8]:2,[edi+10]:2,[edi],[edi+4]
|
||||
mov word[ConfPacket], (FTDI_DEVICE_OUT_REQTYPE) \
|
||||
+ (SIO_SET_BITMODE_REQUEST shl 8)
|
||||
jmp .ftdi_out_control_transfer_withinp
|
||||
|
||||
.ftdi_set_line_property:
|
||||
DEBUGF L_DBG, 'ftdi: Set line property 0x%x PID: %d Dev handler 0x0x%x\n', \
|
||||
DEBUGF 2, 'K : FTDI Set line property 0x%x PID: %d Dev handler 0x0x%x\n', \
|
||||
[edi+8]:4,[edi],[edi+4]
|
||||
mov word[ConfPacket], (FTDI_DEVICE_OUT_REQTYPE) \
|
||||
+ (SIO_SET_DATA_REQUEST shl 8)
|
||||
jmp .ftdi_out_control_transfer_withinp
|
||||
|
||||
.ftdi_set_latency_timer:
|
||||
DEBUGF L_DBG, 'ftdi: Set latency %d PID: %d Dev handler 0x0x%x\n', \
|
||||
DEBUGF 2, 'K : FTDI Set latency %d PID: %d Dev handler 0x0x%x\n', \
|
||||
[edi+8],[edi],[edi+4]
|
||||
mov word[ConfPacket], (FTDI_DEVICE_OUT_REQTYPE) \
|
||||
+ (SIO_SET_LATENCY_TIMER_REQUEST shl 8)
|
||||
jmp .ftdi_out_control_transfer_withinp
|
||||
|
||||
.ftdi_set_event_char:
|
||||
DEBUGF L_DBG, 'ftdi: Set event char %c PID: %d Dev handler 0x0x%x\n', \
|
||||
DEBUGF 2, 'K : FTDI Set event char %c PID: %d Dev handler 0x0x%x\n', \
|
||||
[edi+8],[edi],[edi+4]
|
||||
mov word[ConfPacket], (FTDI_DEVICE_OUT_REQTYPE) \
|
||||
+ (SIO_SET_EVENT_CHAR_REQUEST shl 8)
|
||||
jmp .ftdi_out_control_transfer_withinp
|
||||
|
||||
.ftdi_set_error_char:
|
||||
DEBUGF L_DBG, 'ftdi: Set error char %c PID: %d Dev handler 0x0x%x\n', \
|
||||
DEBUGF 2, 'K : FTDI Set error char %c PID: %d Dev handler 0x0x%x\n', \
|
||||
[edi+8],[edi],[edi+4]
|
||||
mov word[ConfPacket], (FTDI_DEVICE_OUT_REQTYPE) \
|
||||
+ (SIO_SET_ERROR_CHAR_REQUEST shl 8)
|
||||
jmp .ftdi_out_control_transfer_withinp
|
||||
|
||||
.ftdi_setflowctrl:
|
||||
DEBUGF L_DBG, 'ftdi: Set flow control PID: %d Dev handler 0x0x%x\n', [edi],\
|
||||
DEBUGF 2, 'K : FTDI Set flow control PID: %d Dev handler 0x0x%x\n', [edi],\
|
||||
[edi+4]
|
||||
mov dword[ConfPacket], (FTDI_DEVICE_OUT_REQTYPE) \
|
||||
+ (SIO_SET_FLOW_CTRL_REQUEST shl 8) + (0 shl 16)
|
||||
@@ -579,7 +569,7 @@ endl
|
||||
jmp .own_index
|
||||
|
||||
.ftdi_read_pins:
|
||||
DEBUGF L_DBG, 'ftdi: Read pins PID: %d Dev handler 0x0x%x\n', [edi],\
|
||||
DEBUGF 2, 'K : FTDI Read pins PID: %d Dev handler 0x0x%x\n', [edi],\
|
||||
[edi+4]
|
||||
mov ebx, [edi+4]
|
||||
mov dword[ConfPacket], (FTDI_DEVICE_IN_REQTYPE) \
|
||||
@@ -608,7 +598,7 @@ endl
|
||||
jmp .error
|
||||
|
||||
.ftdi_set_wchunksize:
|
||||
DEBUGF L_DBG, 'ftdi: Set write chunksize %d bytes PID: %d Dev handler 0x0x%x\n', \
|
||||
DEBUGF 2, 'K : FTDI Set write chunksize %d bytes PID: %d Dev handler 0x0x%x\n', \
|
||||
[edi+8], [edi], [edi+4]
|
||||
mov ebx, [edi+4]
|
||||
mov ecx, [edi+8]
|
||||
@@ -618,7 +608,7 @@ endl
|
||||
jmp .endswitch
|
||||
|
||||
.ftdi_get_wchunksize:
|
||||
DEBUGF L_DBG, 'ftdi: Get write chunksize PID: %d Dev handler 0x0x%x\n', [edi],\
|
||||
DEBUGF 2, 'K : FTDI Get write chunksize PID: %d Dev handler 0x0x%x\n', [edi],\
|
||||
[edi+4]
|
||||
mov esi, [edi+output]
|
||||
mov edi, [edi+input]
|
||||
@@ -628,7 +618,7 @@ endl
|
||||
jmp .endswitch
|
||||
|
||||
.ftdi_set_rchunksize:
|
||||
DEBUGF L_DBG, 'ftdi: Set read chunksize %d bytes PID: %d Dev handler 0x0x%x\n', \
|
||||
DEBUGF 2, 'K : FTDI Set read chunksize %d bytes PID: %d Dev handler 0x0x%x\n', \
|
||||
[edi+8], [edi], [edi+4]
|
||||
mov ebx, [edi+4]
|
||||
mov ecx, [edi+8]
|
||||
@@ -638,7 +628,7 @@ endl
|
||||
jmp .endswitch
|
||||
|
||||
.ftdi_get_rchunksize:
|
||||
DEBUGF L_DBG, 'ftdi: Get read chunksize PID: %d Dev handler 0x0x%x\n', [edi],\
|
||||
DEBUGF 2, 'K : FTDI Get read chunksize PID: %d Dev handler 0x0x%x\n', [edi],\
|
||||
[edi+4]
|
||||
mov esi, [edi+output]
|
||||
mov edi, [edi+input]
|
||||
@@ -648,7 +638,7 @@ endl
|
||||
jmp .endswitch
|
||||
|
||||
.ftdi_write_data:
|
||||
DEBUGF L_DBG, 'ftdi: Write %d bytes PID: %d Dev handler 0x%x\n', [edi+8],\
|
||||
DEBUGF 2, 'K : FTDI Write %d bytes PID: %d Dev handler 0x%x\n', [edi+8],\
|
||||
[edi], [edi+4]
|
||||
mov esi, edi
|
||||
add esi, 12
|
||||
@@ -695,7 +685,7 @@ endl
|
||||
jmp .write_loop
|
||||
|
||||
.ftdi_read_data:
|
||||
DEBUGF L_DBG, 'ftdi: Read %d bytes PID: %d Dev handler 0x%x\n', [edi+8],\
|
||||
DEBUGF 2, 'K : FTDI Read %d bytes PID: %d Dev handler 0x%x\n', [edi+8],\
|
||||
[edi], [edi+4]
|
||||
mov edi, [ioctl]
|
||||
mov esi, [edi+input]
|
||||
@@ -753,7 +743,7 @@ endl
|
||||
;---Dirty hack end
|
||||
|
||||
.ftdi_poll_modem_status:
|
||||
DEBUGF L_DBG, 'ftdi: Poll modem status PID: %d Dev handler 0x0x%x\n', [edi],\
|
||||
DEBUGF 2, 'K : FTDI Poll modem status PID: %d Dev handler 0x0x%x\n', [edi],\
|
||||
[edi+4]
|
||||
mov ebx, [edi+4]
|
||||
mov dword[ConfPacket], (FTDI_DEVICE_IN_REQTYPE) \
|
||||
@@ -777,7 +767,7 @@ endl
|
||||
jmp .endswitch
|
||||
|
||||
.ftdi_get_latency_timer:
|
||||
DEBUGF L_DBG, 'ftdi: Get latency timer PID: %d Dev handler 0x0x%x\n', [edi],\
|
||||
DEBUGF 2, 'K : FTDI Get latency timer PID: %d Dev handler 0x0x%x\n', [edi],\
|
||||
[edi+4]
|
||||
mov ebx, [edi+4]
|
||||
mov dword[ConfPacket], FTDI_DEVICE_IN_REQTYPE \
|
||||
@@ -797,7 +787,7 @@ endl
|
||||
jmp .endswitch
|
||||
|
||||
.ftdi_get_list:
|
||||
DEBUGF L_DBG, 'ftdi: devices list request\n'
|
||||
DEBUGF 2, 'K : FTDI devices list request\n'
|
||||
mov edi, [edi+output]
|
||||
xor ecx, ecx
|
||||
call linkedlist_gethead
|
||||
@@ -827,7 +817,7 @@ endl
|
||||
jmp .endswitch
|
||||
|
||||
.ftdi_lock:
|
||||
DEBUGF L_DBG, 'ftdi: Lock PID: %d Dev handler 0x0x%x\n', [edi], [edi+4]
|
||||
DEBUGF 2, 'K : FTDI Lock PID: %d Dev handler 0x0x%x\n', [edi], [edi+4]
|
||||
mov esi, [edi+input]
|
||||
mov ebx, [esi+4]
|
||||
mov eax, [ebx + ftdi_context.lockPID]
|
||||
@@ -841,7 +831,7 @@ endl
|
||||
jmp .endswitch
|
||||
|
||||
.ftdi_unlock:
|
||||
DEBUGF L_DBG, 'ftdi: Unlock PID: %d Dev handler 0x0x%x\n', [edi], [edi+4]
|
||||
DEBUGF 2, 'K : FTDI Unlock PID: %d Dev handler 0x0x%x\n', [edi], [edi+4]
|
||||
mov esi, [edi+input]
|
||||
mov edi, [edi+output]
|
||||
mov ebx, [esi+4]
|
||||
@@ -855,19 +845,145 @@ endl
|
||||
mov [edi], eax
|
||||
jmp .endswitch
|
||||
|
||||
H_CLK = 120000000
|
||||
C_CLK = 48000000
|
||||
.ftdi_set_baudrate:
|
||||
DEBUGF L_DBG, 'ftdi: Set baudrate to %d PID: %d Dev handle: 0x%x\n',\
|
||||
DEBUGF 2, 'K : FTDI Set baudrate to %d PID: %d Dev handle: 0x%x\n',\
|
||||
[edi+8], [edi], [edi+4]
|
||||
mov ebx, [edi+4]
|
||||
mov esi, [edi+8]
|
||||
call ftdi_calc_baud_divisor
|
||||
cmp [ebx + ftdi_context.chipType], TYPE_2232H
|
||||
jl .c_clk
|
||||
imul eax, [edi+8], 10
|
||||
cmp eax, H_CLK / 0x3FFF
|
||||
jle .c_clk
|
||||
.h_clk:
|
||||
cmp dword[edi+8], H_CLK/10
|
||||
jl .h_nextbaud1
|
||||
xor edx, edx
|
||||
mov ecx, H_CLK/10
|
||||
jmp .calcend
|
||||
|
||||
.c_clk:
|
||||
cmp dword[edi+8], C_CLK/16
|
||||
jl .c_nextbaud1
|
||||
xor edx, edx
|
||||
mov ecx, C_CLK/16
|
||||
jmp .calcend
|
||||
|
||||
.h_nextbaud1:
|
||||
cmp dword[edi+8], H_CLK/(10 + 10/2)
|
||||
jl .h_nextbaud2
|
||||
mov edx, 1
|
||||
mov ecx, H_CLK/(10 + 10/2)
|
||||
jmp .calcend
|
||||
|
||||
.c_nextbaud1:
|
||||
cmp dword[edi+8], C_CLK/(16 + 16/2)
|
||||
jl .c_nextbaud2
|
||||
mov edx, 1
|
||||
mov ecx, C_CLK/(16 + 16/2)
|
||||
jmp .calcend
|
||||
|
||||
.h_nextbaud2:
|
||||
cmp dword[edi+8], H_CLK/(2*10)
|
||||
jl .h_nextbaud3
|
||||
mov edx, 2
|
||||
mov ecx, H_CLK/(2*10)
|
||||
jmp .calcend
|
||||
|
||||
.c_nextbaud2:
|
||||
cmp dword[edi+8], C_CLK/(2*16)
|
||||
jl .c_nextbaud3
|
||||
mov edx, 2
|
||||
mov ecx, C_CLK/(2*16)
|
||||
jmp .calcend
|
||||
|
||||
.h_nextbaud3:
|
||||
mov eax, H_CLK*16/10 ; eax - best_divisor
|
||||
xor edx, edx
|
||||
div dword[edi+8] ; [edi+8] - baudrate
|
||||
push eax
|
||||
and eax, 1
|
||||
pop eax
|
||||
shr eax, 1
|
||||
jz .h_rounddowndiv ; jump by result of and eax, 1
|
||||
inc eax
|
||||
.h_rounddowndiv:
|
||||
cmp eax, 0x20000
|
||||
jle .h_best_divok
|
||||
mov eax, 0x1FFFF
|
||||
.h_best_divok:
|
||||
mov ecx, eax
|
||||
mov eax, H_CLK*16/10
|
||||
xor edx, edx
|
||||
div ecx
|
||||
xchg ecx, eax ; ecx - best_baud
|
||||
push ecx
|
||||
and ecx, 1
|
||||
pop ecx
|
||||
shr ecx, 1
|
||||
jz .rounddownbaud
|
||||
inc ecx
|
||||
jmp .rounddownbaud
|
||||
|
||||
.c_nextbaud3:
|
||||
mov eax, C_CLK ; eax - best_divisor
|
||||
xor edx, edx
|
||||
div dword[edi+8] ; [edi+8] - baudrate
|
||||
push eax
|
||||
and eax, 1
|
||||
pop eax
|
||||
shr eax, 1
|
||||
jnz .c_rounddowndiv ; jump by result of and eax, 1
|
||||
inc eax
|
||||
.c_rounddowndiv:
|
||||
cmp eax, 0x20000
|
||||
jle .c_best_divok
|
||||
mov eax, 0x1FFFF
|
||||
.c_best_divok:
|
||||
mov ecx, eax
|
||||
mov eax, C_CLK
|
||||
xor edx, edx
|
||||
div ecx
|
||||
xchg ecx, eax ; ecx - best_baud
|
||||
push ecx
|
||||
and ecx, 1
|
||||
pop ecx
|
||||
shr ecx, 1
|
||||
jnz .rounddownbaud
|
||||
inc ecx
|
||||
|
||||
.rounddownbaud:
|
||||
mov edx, eax ; edx - encoded_divisor
|
||||
shr edx, 3
|
||||
and eax, 0x7
|
||||
push 7 6 5 1 4 2 3 0
|
||||
mov eax, [esp+eax*4]
|
||||
shl eax, 14
|
||||
or edx, eax
|
||||
add esp, 32
|
||||
|
||||
.calcend:
|
||||
mov eax, edx ; eax - *value
|
||||
mov ecx, edx ; ecx - *index
|
||||
and eax, 0xFFFF
|
||||
cmp [ebx + ftdi_context.chipType], TYPE_2232H
|
||||
jge .foxyindex
|
||||
shr ecx, 16
|
||||
jmp .preparepacket
|
||||
.foxyindex:
|
||||
shr ecx, 8
|
||||
and ecx, 0xFF00
|
||||
or ecx, [ebx + ftdi_context.index]
|
||||
|
||||
.preparepacket:
|
||||
mov word[ConfPacket], (FTDI_DEVICE_OUT_REQTYPE) \
|
||||
+ (SIO_SET_BAUDRATE_REQUEST shl 8)
|
||||
mov word[ConfPacket+2], ax
|
||||
mov word[ConfPacket+4], cx
|
||||
mov word[ConfPacket+6], 0
|
||||
jmp .own_index
|
||||
|
||||
jmp .own_index
|
||||
|
||||
endp
|
||||
restore handle
|
||||
restore io_code
|
||||
@@ -877,143 +993,10 @@ restore output
|
||||
restore out_size
|
||||
|
||||
|
||||
proc ftdi_calc_baud_divisor
|
||||
; in: ebx = ftdi_context pointer
|
||||
; esi = baud rate
|
||||
; out: ax = encoded value
|
||||
; cx = encoded index
|
||||
; destroys: eax, ecx, edx, esi
|
||||
cmp [ebx + ftdi_context.chipType], TYPE_2232H
|
||||
jl .c_clk
|
||||
imul eax, esi, 10
|
||||
cmp eax, H_CLK / 0x3FFF
|
||||
jle .c_clk
|
||||
.h_clk:
|
||||
cmp esi, H_CLK / 10
|
||||
jl .h_nextbaud1
|
||||
xor edx, edx
|
||||
mov ecx, H_CLK / 10
|
||||
jmp .calcend
|
||||
|
||||
.c_clk:
|
||||
cmp esi, C_CLK / 16
|
||||
jl .c_nextbaud1
|
||||
xor edx, edx
|
||||
mov ecx, C_CLK / 16
|
||||
jmp .calcend
|
||||
|
||||
.h_nextbaud1:
|
||||
cmp esi, H_CLK / (10 + 10 / 2)
|
||||
jl .h_nextbaud2
|
||||
mov edx, 1
|
||||
mov ecx, H_CLK / (10 + 10 / 2)
|
||||
jmp .calcend
|
||||
|
||||
.c_nextbaud1:
|
||||
cmp esi, C_CLK / (16 + 16 / 2)
|
||||
jl .c_nextbaud2
|
||||
mov edx, 1
|
||||
mov ecx, C_CLK/(16 + 16 / 2)
|
||||
jmp .calcend
|
||||
|
||||
.h_nextbaud2:
|
||||
cmp esi, H_CLK / (2 * 10)
|
||||
jl .h_nextbaud3
|
||||
mov edx, 2
|
||||
mov ecx, H_CLK / (2 * 10)
|
||||
jmp .calcend
|
||||
|
||||
.c_nextbaud2:
|
||||
cmp esi, C_CLK / (2 * 16)
|
||||
jl .c_nextbaud3
|
||||
mov edx, 2
|
||||
mov ecx, C_CLK / (2 * 16)
|
||||
jmp .calcend
|
||||
|
||||
.h_nextbaud3:
|
||||
mov eax, H_CLK * 16 / 10 ; eax - best_divisor
|
||||
xor edx, edx
|
||||
div esi
|
||||
push eax
|
||||
and eax, 1
|
||||
pop eax
|
||||
shr eax, 1
|
||||
jz .h_rounddowndiv ; jump by result of and eax, 1
|
||||
inc eax
|
||||
.h_rounddowndiv:
|
||||
cmp eax, 0x20000
|
||||
jle .h_best_divok
|
||||
mov eax, 0x1FFFF
|
||||
.h_best_divok:
|
||||
mov ecx, eax
|
||||
mov eax, H_CLK * 16 / 10
|
||||
xor edx, edx
|
||||
div ecx
|
||||
xchg ecx, eax ; ecx - best_baud
|
||||
push ecx
|
||||
and ecx, 1
|
||||
pop ecx
|
||||
shr ecx, 1
|
||||
jz .rounddownbaud
|
||||
inc ecx
|
||||
jmp .rounddownbaud
|
||||
|
||||
.c_nextbaud3:
|
||||
mov eax, C_CLK ; eax - best_divisor
|
||||
xor edx, edx
|
||||
div esi
|
||||
push eax
|
||||
and eax, 1
|
||||
pop eax
|
||||
shr eax, 1
|
||||
jnz .c_rounddowndiv ; jump by result of and eax, 1
|
||||
inc eax
|
||||
.c_rounddowndiv:
|
||||
cmp eax, 0x20000
|
||||
jle .c_best_divok
|
||||
mov eax, 0x1FFFF
|
||||
.c_best_divok:
|
||||
mov ecx, eax
|
||||
mov eax, C_CLK
|
||||
xor edx, edx
|
||||
div ecx
|
||||
xchg ecx, eax ; ecx - best_baud
|
||||
push ecx
|
||||
and ecx, 1
|
||||
pop ecx
|
||||
shr ecx, 1
|
||||
jnz .rounddownbaud
|
||||
inc ecx
|
||||
|
||||
.rounddownbaud:
|
||||
mov edx, eax ; edx - encoded_divisor
|
||||
shr edx, 3
|
||||
and eax, 0x7
|
||||
push 7 6 5 1 4 2 3 0
|
||||
mov eax, [esp + eax * 4]
|
||||
shl eax, 14
|
||||
or edx, eax
|
||||
add esp, 32
|
||||
|
||||
.calcend:
|
||||
mov eax, edx ; eax - *value
|
||||
mov ecx, edx ; ecx - *index
|
||||
and eax, 0xFFFF
|
||||
cmp [ebx + ftdi_context.chipType], TYPE_2232H
|
||||
jge .foxyindex
|
||||
shr ecx, 16
|
||||
ret
|
||||
.foxyindex:
|
||||
shr ecx, 8
|
||||
and ecx, 0xFF00
|
||||
or ecx, [ebx + ftdi_context.index]
|
||||
ret
|
||||
endp
|
||||
|
||||
proc control_callback stdcall uses ebx edi esi, .pipe:DWORD, .status:DWORD, \
|
||||
.buffer:DWORD, .length:DWORD, .calldata:DWORD
|
||||
|
||||
DEBUGF L_DBG, 'ftdi: status is %d\n', [.status]
|
||||
DEBUGF 1, 'K : status is %d\n', [.status]
|
||||
mov ecx, [.calldata]
|
||||
mov eax, [ecx]
|
||||
mov ebx, [ecx+4]
|
||||
@@ -1028,7 +1011,7 @@ endp
|
||||
proc bulk_callback stdcall uses ebx edi esi, .pipe:DWORD, .status:DWORD, \
|
||||
.buffer:DWORD, .length:DWORD, .calldata:DWORD
|
||||
|
||||
DEBUGF L_DBG, 'ftdi: status is %d\n', [.status]
|
||||
DEBUGF 1, 'K : status is %d\n', [.status]
|
||||
mov ecx, [.calldata]
|
||||
mov eax, [ecx]
|
||||
mov ebx, [ecx+4]
|
||||
@@ -1051,7 +1034,7 @@ endp
|
||||
|
||||
proc DeviceDisconnected stdcall uses ebx esi edi, .device_data:DWORD
|
||||
|
||||
DEBUGF L_DBG, 'ftdi: deleting device data 0x%x\n', [.device_data]
|
||||
DEBUGF 1, 'K : FTDI deleting device data 0x%x\n', [.device_data]
|
||||
mov esi, [.device_data]
|
||||
mov eax, [esi + ftdi_context.readBufPtr]
|
||||
test eax, eax
|
||||
@@ -1079,7 +1062,7 @@ proc bulk_in_complete stdcall uses ebx edi esi, .pipe:DWORD, .status:DWORD, \
|
||||
mov eax, [.status]
|
||||
test eax, eax
|
||||
jz @f
|
||||
DEBUGF L_ERR, 'ftdi: bulk in error %x\n', eax
|
||||
DEBUGF 2, 'ftdi: bulk in error %x\n', eax
|
||||
@@:
|
||||
mov ebx, [.calldata]
|
||||
btr dword [ebx + ftdi_context.writeBufLock], 0
|
||||
@@ -1092,7 +1075,7 @@ proc bulk_out_complete stdcall uses ebx edi esi, .pipe:DWORD, .status:DWORD, \
|
||||
mov eax, [.status]
|
||||
test eax, eax
|
||||
jz @f
|
||||
DEBUGF L_ERR, 'ftdi: bulk out error %x\n', eax
|
||||
DEBUGF 2, 'ftdi: bulk out error %x\n', eax
|
||||
@@:
|
||||
mov ebx, [.calldata]
|
||||
mov ecx, [.length]
|
||||
@@ -1109,18 +1092,18 @@ proc bulk_out_complete stdcall uses ebx edi esi, .pipe:DWORD, .status:DWORD, \
|
||||
endp
|
||||
|
||||
proc uart_startup stdcall uses ebx, data:dword, conf:dword
|
||||
DEBUGF L_DBG, "ftdi: startup %x %x\n", [data], [conf]
|
||||
DEBUGF 1, "ftdi: startup %x %x\n", [data], [conf]
|
||||
stdcall uart_reconf, [data], [conf]
|
||||
test eax, eax
|
||||
jz @f
|
||||
DEBUGF L_ERR, "ftdi: uart reconf error %x\n", eax
|
||||
DEBUGF 2, "ftdi: uart reconf error %x\n", eax
|
||||
jmp .exit
|
||||
@@:
|
||||
mov ebx, [data]
|
||||
invoke TimerHS, 2, 2, uart_rx, ebx
|
||||
test eax, eax
|
||||
jnz @f
|
||||
DEBUGF L_ERR, "ftdi: timer creation error\n"
|
||||
DEBUGF 2, "ftdi: timer creation error\n"
|
||||
or eax, -1
|
||||
jmp .exit
|
||||
@@:
|
||||
@@ -1131,7 +1114,7 @@ proc uart_startup stdcall uses ebx, data:dword, conf:dword
|
||||
endp
|
||||
|
||||
proc uart_shutdown stdcall uses ebx, data:dword
|
||||
DEBUGF L_DBG, "ftdi: shutdown %x\n", [data]
|
||||
DEBUGF 1, "ftdi: shutdown %x\n", [data]
|
||||
mov ebx, [data]
|
||||
cmp [ebx + ftdi_context.rx_timer], 0
|
||||
jz @f
|
||||
@@ -1263,14 +1246,137 @@ proc uart_rx stdcall uses ebx esi, data:dword
|
||||
ret
|
||||
endp
|
||||
|
||||
proc ftdi_set_baudrate stdcall uses ebx esi, dev:dword, baud:dword
|
||||
proc ftdi_set_baudrate stdcall uses ebx, dev:dword, baud:dword
|
||||
locals
|
||||
ConfPacket rb 8
|
||||
endl
|
||||
mov ebx, [dev]
|
||||
mov esi, [baud]
|
||||
call ftdi_calc_baud_divisor
|
||||
cmp [ebx + ftdi_context.chipType], TYPE_2232H
|
||||
jl .c_clk
|
||||
imul eax, [baud], 10
|
||||
cmp eax, H_CLK / 0x3FFF
|
||||
jle .c_clk
|
||||
.h_clk:
|
||||
cmp dword [baud], H_CLK / 10
|
||||
jl .h_nextbaud1
|
||||
xor edx, edx
|
||||
mov ecx, H_CLK / 10
|
||||
jmp .calcend
|
||||
|
||||
.c_clk:
|
||||
cmp dword [baud], C_CLK / 16
|
||||
jl .c_nextbaud1
|
||||
xor edx, edx
|
||||
mov ecx, C_CLK / 16
|
||||
jmp .calcend
|
||||
|
||||
.h_nextbaud1:
|
||||
cmp dword [baud], H_CLK / (10 + 10 / 2)
|
||||
jl .h_nextbaud2
|
||||
mov edx, 1
|
||||
mov ecx, H_CLK / (10 + 10 / 2)
|
||||
jmp .calcend
|
||||
|
||||
.c_nextbaud1:
|
||||
cmp dword [baud], C_CLK / (16 + 16 / 2)
|
||||
jl .c_nextbaud2
|
||||
mov edx, 1
|
||||
mov ecx, C_CLK/(16 + 16 / 2)
|
||||
jmp .calcend
|
||||
|
||||
.h_nextbaud2:
|
||||
cmp dword [baud], H_CLK / (2 * 10)
|
||||
jl .h_nextbaud3
|
||||
mov edx, 2
|
||||
mov ecx, H_CLK / (2 * 10)
|
||||
jmp .calcend
|
||||
|
||||
.c_nextbaud2:
|
||||
cmp dword [baud], C_CLK / (2 * 16)
|
||||
jl .c_nextbaud3
|
||||
mov edx, 2
|
||||
mov ecx, C_CLK / (2 * 16)
|
||||
jmp .calcend
|
||||
|
||||
.h_nextbaud3:
|
||||
mov eax, H_CLK * 16 / 10 ; eax - best_divisor
|
||||
xor edx, edx
|
||||
div dword [baud]
|
||||
push eax
|
||||
and eax, 1
|
||||
pop eax
|
||||
shr eax, 1
|
||||
jz .h_rounddowndiv ; jump by result of and eax, 1
|
||||
inc eax
|
||||
.h_rounddowndiv:
|
||||
cmp eax, 0x20000
|
||||
jle .h_best_divok
|
||||
mov eax, 0x1FFFF
|
||||
.h_best_divok:
|
||||
mov ecx, eax
|
||||
mov eax, H_CLK * 16 / 10
|
||||
xor edx, edx
|
||||
div ecx
|
||||
xchg ecx, eax ; ecx - best_baud
|
||||
push ecx
|
||||
and ecx, 1
|
||||
pop ecx
|
||||
shr ecx, 1
|
||||
jz .rounddownbaud
|
||||
inc ecx
|
||||
jmp .rounddownbaud
|
||||
|
||||
.c_nextbaud3:
|
||||
mov eax, C_CLK ; eax - best_divisor
|
||||
xor edx, edx
|
||||
div dword [baud]
|
||||
push eax
|
||||
and eax, 1
|
||||
pop eax
|
||||
shr eax, 1
|
||||
jnz .c_rounddowndiv ; jump by result of and eax, 1
|
||||
inc eax
|
||||
.c_rounddowndiv:
|
||||
cmp eax, 0x20000
|
||||
jle .c_best_divok
|
||||
mov eax, 0x1FFFF
|
||||
.c_best_divok:
|
||||
mov ecx, eax
|
||||
mov eax, C_CLK
|
||||
xor edx, edx
|
||||
div ecx
|
||||
xchg ecx, eax ; ecx - best_baud
|
||||
push ecx
|
||||
and ecx, 1
|
||||
pop ecx
|
||||
shr ecx, 1
|
||||
jnz .rounddownbaud
|
||||
inc ecx
|
||||
|
||||
.rounddownbaud:
|
||||
mov edx, eax ; edx - encoded_divisor
|
||||
shr edx, 3
|
||||
and eax, 0x7
|
||||
push 7 6 5 1 4 2 3 0
|
||||
mov eax, [esp + eax * 4]
|
||||
shl eax, 14
|
||||
or edx, eax
|
||||
add esp, 32
|
||||
|
||||
.calcend:
|
||||
mov eax, edx ; eax - *value
|
||||
mov ecx, edx ; ecx - *index
|
||||
and eax, 0xFFFF
|
||||
cmp [ebx + ftdi_context.chipType], TYPE_2232H
|
||||
jge .foxyindex
|
||||
shr ecx, 16
|
||||
jmp .preparepacket
|
||||
.foxyindex:
|
||||
shr ecx, 8
|
||||
and ecx, 0xFF00
|
||||
or ecx, [ebx + ftdi_context.index]
|
||||
|
||||
.preparepacket:
|
||||
mov word [ConfPacket], (FTDI_DEVICE_OUT_REQTYPE) \
|
||||
+ (SIO_SET_BAUDRATE_REQUEST shl 8)
|
||||
mov word [ConfPacket + 2], ax
|
||||
@@ -1345,9 +1451,10 @@ uart_drv:
|
||||
dd uart_tx
|
||||
uart_drv_end:
|
||||
|
||||
include_debug_strings
|
||||
serial_drv_entry dd 0
|
||||
|
||||
data fixups
|
||||
end data
|
||||
|
||||
serial_drv_entry dd ?
|
||||
|
||||
;for DEBUGF macro
|
||||
include_debug_strings
|
||||
@@ -2204,9 +2204,6 @@ proc acm_arm_rx
|
||||
endp
|
||||
|
||||
proc acm_add_device stdcall uses ebx esi edi, .pipe0:dword, .config:dword, .interface:dword
|
||||
locals
|
||||
.pinfo rb sizeof.SP_PORT_INFO
|
||||
endl
|
||||
|
||||
; 1. Parse the descriptors (the ACM data interface is alt setting 0).
|
||||
xor eax, eax
|
||||
@@ -2267,12 +2264,7 @@ endl
|
||||
|
||||
cmp [serial_drv_entry], 0
|
||||
je .no_serial
|
||||
mov dword [.pinfo+SP_PORT_INFO.size], sizeof.SP_PORT_INFO
|
||||
mov dword [.pinfo+SP_PORT_INFO.driver], acm_port_name
|
||||
; TODO obtain iManufacturer, iProduct and iSerial strings
|
||||
mov dword [.pinfo+SP_PORT_INFO.descr], 0
|
||||
lea ecx, [.pinfo]
|
||||
stdcall serial_add_port, acm_sp_driver, ebx, ecx
|
||||
stdcall serial_add_port, acm_sp_driver, ebx
|
||||
mov [ebx+acm_dev.PortHandle], eax
|
||||
test eax, eax
|
||||
jz .no_serial
|
||||
@@ -2660,7 +2652,6 @@ endp
|
||||
|
||||
; strings and static data
|
||||
my_service db 'usbcdc', 0
|
||||
acm_port_name db 'cdc-acm', 0
|
||||
netdev_name db 'USB CDC-NCM', 0
|
||||
ecm_netdev_name db 'USB CDC-ECM', 0
|
||||
ecm_zlp_dummy db 0 ; address for zero-length transfers
|
||||
|
||||
@@ -1754,14 +1754,8 @@ proc disk_read_write stdcall uses ebx esi edi, \
|
||||
mov eax, [numsectors]
|
||||
mov eax, [eax]
|
||||
; 2. The transfer length for SCSI_{READ,WRITE}10 commands can not be greater
|
||||
; than 0xFFFF sectors, but that is not the practical limit: the field size is
|
||||
; the only thing the standard bounds, while real sticks hang their firmware on
|
||||
; multi-megabyte single commands. The kernel disk cache asks for as much as
|
||||
; CACHE_MAX_ALLOC_SIZE (4 MB) in one call, i.e. 8192 sectors, and that is
|
||||
; exactly where such sticks stop answering and re-enumerate. Linux caps
|
||||
; usb-storage at 240 sectors (120 KB) for the same reason; do the same and
|
||||
; split larger requests into slices.
|
||||
max_sectors_at_time = 240
|
||||
; than 0xFFFF, so split the request to slices with <= 0xFFFF sectors.
|
||||
max_sectors_at_time = 0xFFFF
|
||||
.split:
|
||||
push eax ; .length_rest
|
||||
cmp eax, max_sectors_at_time
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
if tup.getconfig("NO_FASM") ~= "" then return end
|
||||
ROOT = "../../.."
|
||||
tup.rule("xhci.asm", "fasm %f %o " .. tup.getconfig("PESTRIP_CMD") .. tup.getconfig("KPACK_CMD"), "%B.sys")
|
||||
File diff suppressed because it is too large.
Load diff
@@ -1,993 +0,0 @@
|
||||
; Device slots, contexts and pipes for the xHCI driver.
|
||||
; This file is included from xhci.asm.
|
||||
|
||||
; =============================================================================
|
||||
; ============================ Context helpers ================================
|
||||
; =============================================================================
|
||||
|
||||
; Returns the address of one context inside a context structure.
|
||||
; in: eax = base of the structure, ecx = index of the context,
|
||||
; esi -> usb_controller.
|
||||
; out: eax = address of the context.
|
||||
proc xhci_context
|
||||
push ecx edx
|
||||
mov edx, [esi+xhci_controller.ContextSize-XCD]
|
||||
imul edx, ecx
|
||||
add eax, edx
|
||||
pop edx ecx
|
||||
ret
|
||||
endp
|
||||
|
||||
; Zeroes the Input Context. The caller must hold CmdLock.
|
||||
; in: esi -> usb_controller.
|
||||
proc xhci_clear_input_ctx
|
||||
push eax ecx edi
|
||||
mov edi, [esi+xhci_controller.InputCtx-XCD]
|
||||
xor eax, eax
|
||||
mov ecx, 33*64/4
|
||||
rep stosd
|
||||
pop edi ecx eax
|
||||
ret
|
||||
endp
|
||||
|
||||
; Returns the pipe of the default control endpoint of the same device, which
|
||||
; represents the device as a whole.
|
||||
; in: ebx -> xhci_pipe. out: eax -> xhci_pipe or 0.
|
||||
proc xhci_ctrl_pipe
|
||||
mov eax, [ebx+xhci_pipe.DevPage]
|
||||
test eax, eax
|
||||
jz .nothing
|
||||
mov eax, [eax+XHCI_PIPES_OFS+1*4]
|
||||
test eax, eax
|
||||
jz .nothing
|
||||
sub eax, sizeof.xhci_pipe
|
||||
.nothing:
|
||||
ret
|
||||
endp
|
||||
|
||||
; Fills the Slot Context of the Input Context from the device description kept
|
||||
; in a pipe. The caller must hold CmdLock.
|
||||
; in: esi -> usb_controller, ebx -> xhci_pipe describing the device,
|
||||
; ecx = value for the Context Entries field.
|
||||
proc xhci_fill_slot_ctx
|
||||
push eax ecx edx edi
|
||||
mov eax, [esi+xhci_controller.InputCtx-XCD]
|
||||
push ecx
|
||||
movi ecx, 1
|
||||
call xhci_context
|
||||
pop ecx
|
||||
mov edi, eax
|
||||
; dword 0: Route String, Speed and Context Entries.
|
||||
mov eax, [ebx+xhci_pipe.Route]
|
||||
and eax, 0FFFFFh
|
||||
if XHCI_SUPERSPEED
|
||||
; A SuperSpeed root-port device carries the raw PORTSC speed identifier;
|
||||
; its kernel-visible Speed pretends high-speed and must not get here.
|
||||
mov edx, [ebx+xhci_pipe.PSIV]
|
||||
test edx, edx
|
||||
jnz .havespeed
|
||||
end if
|
||||
mov edx, [ebx+xhci_pipe.Speed]
|
||||
cmp edx, USB_SPEED_FS
|
||||
jz .fs
|
||||
cmp edx, USB_SPEED_LS
|
||||
jz .ls
|
||||
movi edx, XHCI_PSI_HS
|
||||
jmp .havespeed
|
||||
.fs:
|
||||
movi edx, XHCI_PSI_FS
|
||||
jmp .havespeed
|
||||
.ls:
|
||||
movi edx, XHCI_PSI_LS
|
||||
.havespeed:
|
||||
shl edx, 20
|
||||
or eax, edx
|
||||
shl ecx, 27
|
||||
or eax, ecx
|
||||
mov [edi], eax
|
||||
; dword 1: Root Hub Port Number.
|
||||
mov eax, [ebx+xhci_pipe.RootPort]
|
||||
shl eax, 16
|
||||
mov [edi+4], eax
|
||||
; dword 2: the Transaction Translator, if the device is served by one.
|
||||
mov eax, [ebx+xhci_pipe.TTSlot]
|
||||
test eax, eax
|
||||
jz @f
|
||||
mov edx, [ebx+xhci_pipe.TTPort]
|
||||
shl edx, 8
|
||||
or eax, edx
|
||||
@@:
|
||||
mov [edi+8], eax
|
||||
and dword [edi+12], 0
|
||||
pop edi edx ecx eax
|
||||
ret
|
||||
endp
|
||||
|
||||
; Fills the Endpoint Context of the Input Context for the given pipe.
|
||||
; The caller must hold CmdLock.
|
||||
; in: esi -> usb_controller, ebx -> xhci_pipe.
|
||||
proc xhci_fill_ep_ctx
|
||||
push eax ecx edx edi
|
||||
mov eax, [esi+xhci_controller.InputCtx-XCD]
|
||||
mov ecx, [ebx+xhci_pipe.DCI]
|
||||
inc ecx
|
||||
call xhci_context
|
||||
mov edi, eax
|
||||
; dword 0: Interval.
|
||||
mov eax, [ebx+xhci_pipe.Interval]
|
||||
shl eax, 16
|
||||
mov [edi], eax
|
||||
; dword 1: Error Count, Endpoint Type, Max Burst Size and Max Packet Size.
|
||||
mov eax, [ebx+xhci_pipe.EpType]
|
||||
shl eax, 3
|
||||
or eax, 3 shl 1 ; three retries before giving up
|
||||
mov edx, [ebx+xhci_pipe.MaxPacket]
|
||||
mov ecx, edx
|
||||
shr ecx, 11
|
||||
and ecx, 3 ; extra transactions per microframe
|
||||
shl ecx, 8
|
||||
or eax, ecx
|
||||
if XHCI_SUPERSPEED
|
||||
; A SuperSpeed bulk endpoint may allow bursts of several packets; the field
|
||||
; shares its bits with the extra-transactions ones, which are zero then.
|
||||
mov ecx, [ebx+xhci_pipe.MaxBurst]
|
||||
shl ecx, 8
|
||||
or eax, ecx
|
||||
end if
|
||||
and edx, 7FFh
|
||||
shl edx, 16
|
||||
or eax, edx
|
||||
mov [edi+4], eax
|
||||
; dwords 2 and 3: the TR Dequeue Pointer with the Dequeue Cycle State.
|
||||
mov eax, [ebx+xhci_pipe.Enqueue]
|
||||
shl eax, 4
|
||||
add eax, [ebx+xhci_pipe.RingPhys]
|
||||
or eax, [ebx+xhci_pipe.Cycle]
|
||||
mov [edi+8], eax
|
||||
and dword [edi+12], 0
|
||||
; dword 4: Average TRB Length, only a hint for the bandwidth scheduler.
|
||||
mov eax, [ebx+xhci_pipe.MaxPacket]
|
||||
and eax, 7FFh
|
||||
cmp [ebx+xhci_pipe.EpType], XHCI_EP_CONTROL
|
||||
jnz @f
|
||||
movi eax, 8
|
||||
@@:
|
||||
mov [edi+16], eax
|
||||
and dword [edi+20], 0
|
||||
pop edi edx ecx eax
|
||||
ret
|
||||
endp
|
||||
|
||||
; =============================================================================
|
||||
; ============================== Slot commands ================================
|
||||
; =============================================================================
|
||||
|
||||
; Issues the Address Device command for a newly created default control pipe.
|
||||
; in: esi -> usb_controller, ebx -> xhci_pipe. out: eax = 0 on failure.
|
||||
proc xhci_address_device
|
||||
push ebx ecx edx edi
|
||||
lea ecx, [esi+xhci_controller.CmdLock-XCD]
|
||||
invoke MutexLock
|
||||
call xhci_clear_input_ctx
|
||||
mov edx, [esi+xhci_controller.InputCtx-XCD]
|
||||
mov dword [edx+4], 3 ; add the Slot Context and endpoint zero
|
||||
movi ecx, 1
|
||||
call xhci_fill_slot_ctx
|
||||
call xhci_fill_ep_ctx
|
||||
mov [ebx+xhci_pipe.MaxDCI], 1
|
||||
; Point the DCBAA entry of the slot at the Device Context.
|
||||
mov eax, [esi+xhci_controller.CommonPage-XCD]
|
||||
mov ecx, [ebx+xhci_pipe.SlotId]
|
||||
mov edx, [ebx+xhci_pipe.DevPagePhys]
|
||||
mov [eax+ecx*8], edx
|
||||
and dword [eax+ecx*8+4], 0
|
||||
mov edx, [ebx+xhci_pipe.SlotId]
|
||||
shl edx, 24
|
||||
or edx, XHCI_TRB_ADDRESS_DEV shl 10
|
||||
mov eax, [esi+xhci_controller.InputCtxPhys-XCD]
|
||||
push ebx
|
||||
xor ebx, ebx
|
||||
xor ecx, ecx
|
||||
call xhci_cmd_submit
|
||||
pop ebx
|
||||
push eax
|
||||
lea ecx, [esi+xhci_controller.CmdLock-XCD]
|
||||
invoke MutexUnlock
|
||||
pop eax
|
||||
cmp eax, XHCI_CC_SUCCESS
|
||||
jz .ok
|
||||
DEBUGF 1,'K : XHCI: Address Device failed, code %d\n',eax
|
||||
xor eax, eax
|
||||
jmp .nothing
|
||||
.ok:
|
||||
movi eax, 1
|
||||
.nothing:
|
||||
pop edi edx ecx ebx
|
||||
ret
|
||||
endp
|
||||
|
||||
; Issues a Configure Endpoint command that adds the given endpoint.
|
||||
; in: esi -> usb_controller, ebx -> xhci_pipe of the endpoint,
|
||||
; edi -> xhci_pipe of the default control endpoint of the same device.
|
||||
; out: eax = completion code.
|
||||
proc xhci_configure_endpoint
|
||||
push ebx ecx edx esi edi
|
||||
lea ecx, [esi+xhci_controller.CmdLock-XCD]
|
||||
invoke MutexLock
|
||||
call xhci_clear_input_ctx
|
||||
; Drop the endpoint and add it again, so that reopening an endpoint that has
|
||||
; been closed before also works.
|
||||
mov ecx, [ebx+xhci_pipe.DCI]
|
||||
movi eax, 1
|
||||
shl eax, cl
|
||||
mov edx, [esi+xhci_controller.InputCtx-XCD]
|
||||
mov [edx], eax
|
||||
or eax, 1 ; the Slot Context is always added
|
||||
mov [edx+4], eax
|
||||
call xhci_fill_ep_ctx
|
||||
; The Context Entries field must cover every endpoint in use by the device.
|
||||
mov ecx, [ebx+xhci_pipe.DCI]
|
||||
cmp ecx, [edi+xhci_pipe.MaxDCI]
|
||||
jae @f
|
||||
mov ecx, [edi+xhci_pipe.MaxDCI]
|
||||
@@:
|
||||
mov [edi+xhci_pipe.MaxDCI], ecx
|
||||
push ebx
|
||||
mov ebx, edi
|
||||
call xhci_fill_slot_ctx
|
||||
pop ebx
|
||||
mov edx, [ebx+xhci_pipe.SlotId]
|
||||
shl edx, 24
|
||||
or edx, XHCI_TRB_CONFIG_EP shl 10
|
||||
mov eax, [esi+xhci_controller.InputCtxPhys-XCD]
|
||||
push ebx
|
||||
xor ebx, ebx
|
||||
xor ecx, ecx
|
||||
call xhci_cmd_submit
|
||||
pop ebx
|
||||
push eax
|
||||
lea ecx, [esi+xhci_controller.CmdLock-XCD]
|
||||
invoke MutexUnlock
|
||||
pop eax
|
||||
pop edi esi edx ecx ebx
|
||||
ret
|
||||
endp
|
||||
|
||||
; Tells the controller where the endpoint has to continue from.
|
||||
; in: esi -> usb_controller, ebx -> xhci_pipe.
|
||||
proc xhci_set_dequeue
|
||||
pushad
|
||||
cmp [ebx+xhci_pipe.SlotId], 0
|
||||
jz .nothing
|
||||
mov eax, [ebx+xhci_pipe.Dequeue]
|
||||
shl eax, 4
|
||||
add eax, [ebx+xhci_pipe.RingPhys]
|
||||
or eax, [ebx+xhci_pipe.Cycle]
|
||||
mov ecx, [ebx+xhci_pipe.DCI]
|
||||
shl ecx, 16
|
||||
mov edx, [ebx+xhci_pipe.SlotId]
|
||||
shl edx, 24
|
||||
or edx, ecx
|
||||
or edx, XHCI_TRB_SET_DEQ shl 10
|
||||
xor ebx, ebx
|
||||
xor ecx, ecx
|
||||
call xhci_cmd_sync
|
||||
cmp eax, XHCI_CC_SUCCESS
|
||||
jz .nothing
|
||||
DEBUGF 1,'K : XHCI: Set TR Dequeue Pointer failed, code %d\n',eax
|
||||
.nothing:
|
||||
popad
|
||||
ret
|
||||
endp
|
||||
|
||||
; =============================================================================
|
||||
; =============================== New device ==================================
|
||||
; =============================================================================
|
||||
|
||||
; Called from xhci_port_init and from the hub support code when a new device
|
||||
; has been connected and reset. Enables a device slot for it and hands it over
|
||||
; to the protocol layer.
|
||||
; in: esi -> usb_controller, eax = speed. out: eax = 0 on failure.
|
||||
proc xhci_new_device
|
||||
push ebx ecx edx edi
|
||||
mov [esi+usb_controller.ResettingSpeed], al
|
||||
; 1. Reserve room for the pseudo-pipe that describes the new device. Only the
|
||||
; fields read by xhci_init_pipe are filled in; the layout matches a real pipe,
|
||||
; so the result can be passed to usb_new_device as a usb_pipe pointer.
|
||||
sub esp, sizeof.xhci_pipe + 4
|
||||
mov ebx, esp
|
||||
push ebx
|
||||
mov edi, ebx
|
||||
xor eax, eax
|
||||
mov ecx, (sizeof.xhci_pipe + 4)/4
|
||||
rep stosd
|
||||
pop ebx
|
||||
mov [ebx+sizeof.xhci_pipe], esi ; usb_pipe.Controller
|
||||
movzx eax, [esi+usb_controller.ResettingSpeed]
|
||||
mov [ebx+xhci_pipe.Speed], eax
|
||||
; 2. Compute the root hub port, the route string and the tier of the device.
|
||||
movzx edx, [esi+usb_controller.ResettingPort]
|
||||
mov edi, [esi+usb_controller.ResettingHub]
|
||||
test edi, edi
|
||||
jnz .behind_hub
|
||||
mov eax, [esi+xhci_controller.PortMap-XCD+edx*4]
|
||||
mov [ebx+xhci_pipe.RootPort], eax
|
||||
if XHCI_SUPERSPEED
|
||||
mov eax, [esi+xhci_controller.ResettingPSIV-XCD]
|
||||
mov [ebx+xhci_pipe.PSIV], eax
|
||||
end if
|
||||
jmp .have_topology
|
||||
.behind_hub:
|
||||
; The parent hub is a device too, and its own pipe carries the topology data.
|
||||
mov eax, [edi+USB_HUB_CONFIGPIPE]
|
||||
sub eax, sizeof.xhci_pipe
|
||||
mov ecx, [eax+xhci_pipe.RootPort]
|
||||
mov [ebx+xhci_pipe.RootPort], ecx
|
||||
mov ecx, [eax+xhci_pipe.Depth]
|
||||
mov eax, [eax+xhci_pipe.Route]
|
||||
; The route string holds one nibble per tier, at most five of them.
|
||||
cmp ecx, 5
|
||||
jae .have_route
|
||||
push ecx edx
|
||||
shl ecx, 2
|
||||
inc edx ; the route uses 1-based port numbers
|
||||
cmp edx, 15
|
||||
jbe @f
|
||||
movi edx, 15
|
||||
@@:
|
||||
shl edx, cl
|
||||
or eax, edx
|
||||
pop edx ecx
|
||||
.have_route:
|
||||
inc ecx
|
||||
mov [ebx+xhci_pipe.Depth], ecx
|
||||
mov [ebx+xhci_pipe.Route], eax
|
||||
; 3. Low- and full-speed devices behind a high-speed hub need the address of
|
||||
; the Transaction Translator that serves them.
|
||||
cmp [ebx+xhci_pipe.Speed], USB_SPEED_HS
|
||||
jz .have_topology
|
||||
push ebx
|
||||
mov ecx, edx
|
||||
mov edx, edi
|
||||
invoke usbhc_api.usb_get_tt
|
||||
pop ebx
|
||||
test edx, edx
|
||||
jz .have_topology
|
||||
sub edx, sizeof.xhci_pipe
|
||||
mov eax, [edx+xhci_pipe.SlotId]
|
||||
mov [ebx+xhci_pipe.TTSlot], eax
|
||||
inc ecx
|
||||
mov [ebx+xhci_pipe.TTPort], ecx
|
||||
.have_topology:
|
||||
; 4. Ask the controller for a device slot.
|
||||
xor eax, eax
|
||||
push ebx
|
||||
xor ebx, ebx
|
||||
xor ecx, ecx
|
||||
mov edx, XHCI_TRB_ENABLE_SLOT shl 10
|
||||
call xhci_cmd_sync
|
||||
pop ebx
|
||||
cmp eax, XHCI_CC_SUCCESS
|
||||
jnz .fail
|
||||
test edx, edx
|
||||
jz .fail
|
||||
mov [ebx+xhci_pipe.SlotId], edx
|
||||
DEBUGF 1,'K : XHCI new device: slot %d, root port %d, route %x, speed %d\n',edx,[ebx+xhci_pipe.RootPort],[ebx+xhci_pipe.Route],[ebx+xhci_pipe.Speed]
|
||||
; 5. Hand the device over to the protocol layer. It opens the pipe of the
|
||||
; default control endpoint, and that is where the slot is really addressed.
|
||||
lea ecx, [ebx+sizeof.xhci_pipe]
|
||||
invoke usbhc_api.usb_new_device
|
||||
test eax, eax
|
||||
jnz .done
|
||||
; 6. The protocol layer has failed; release the slot again.
|
||||
mov edx, [ebx+xhci_pipe.SlotId]
|
||||
shl edx, 24
|
||||
or edx, XHCI_TRB_DISABLE_SLOT shl 10
|
||||
xor eax, eax
|
||||
xor ebx, ebx
|
||||
xor ecx, ecx
|
||||
call xhci_cmd_sync
|
||||
xor eax, eax
|
||||
jmp .done
|
||||
.fail:
|
||||
dbgstr 'XHCI: Enable Slot failed'
|
||||
xor eax, eax
|
||||
.done:
|
||||
add esp, sizeof.xhci_pipe + 4
|
||||
pop edi edx ecx ebx
|
||||
ret
|
||||
endp
|
||||
|
||||
; =============================================================================
|
||||
; ================================= Pipes =====================================
|
||||
; =============================================================================
|
||||
|
||||
proc xhci_alloc_pipe
|
||||
push ebx ecx edi
|
||||
mov ebx, xhci_ep_mutex
|
||||
invoke usbhc_api.usb_allocate_common, sizeof.xhci_pipe + sizeof.usb_pipe
|
||||
test eax, eax
|
||||
jz @f
|
||||
; Zero the whole block: the kernel may call FreePipe for a pipe whose InitPipe
|
||||
; has never run, and that path must not act on garbage.
|
||||
mov edi, eax
|
||||
push eax
|
||||
xor eax, eax
|
||||
movi ecx, (sizeof.xhci_pipe + sizeof.usb_pipe + 3)/4
|
||||
rep stosd
|
||||
pop eax
|
||||
add eax, sizeof.xhci_pipe
|
||||
@@:
|
||||
pop edi ecx ebx
|
||||
ret
|
||||
endp
|
||||
|
||||
proc xhci_free_pipe stdcall, ptr:dword
|
||||
push ebx esi edi
|
||||
mov ebx, [ptr]
|
||||
sub ebx, sizeof.xhci_pipe
|
||||
mov esi, [ebx+sizeof.xhci_pipe+usb_pipe.Controller]
|
||||
test esi, esi
|
||||
jz .free
|
||||
cmp [ebx+xhci_pipe.SlotId], 0
|
||||
jz .drop_pipe
|
||||
cmp [ebx+xhci_pipe.DCI], 1
|
||||
jnz .drop_pipe
|
||||
; This is the default control endpoint, that is, the handle of the whole
|
||||
; device: release the slot together with the per-device page.
|
||||
mov ecx, [ebx+xhci_pipe.SlotId]
|
||||
mov edx, ecx
|
||||
shl edx, 24
|
||||
or edx, XHCI_TRB_DISABLE_SLOT shl 10
|
||||
xor eax, eax
|
||||
push ebx
|
||||
xor ebx, ebx
|
||||
xor ecx, ecx
|
||||
call xhci_cmd_sync
|
||||
pop ebx
|
||||
; The controller may access the Device Context until the command above
|
||||
; completes, so only now may the DCBAA entry and the slot table forget it.
|
||||
mov ecx, [ebx+xhci_pipe.SlotId]
|
||||
mov edi, [esi+xhci_controller.CommonPage-XCD]
|
||||
and dword [edi+ecx*8], 0
|
||||
and dword [edi+ecx*8+4], 0
|
||||
and [esi+xhci_controller.SlotPages-XCD+ecx*4], 0
|
||||
mov eax, [ebx+xhci_pipe.DevPage]
|
||||
test eax, eax
|
||||
jz .drop_ring
|
||||
invoke KernelFree, eax
|
||||
and [ebx+xhci_pipe.DevPage], 0
|
||||
jmp .drop_ring
|
||||
.drop_pipe:
|
||||
; Remove the pipe from the per-device table, if it is still listed there.
|
||||
; On disconnect the kernel releases the pipes of a device in arbitrary order,
|
||||
; and the pipe of the default control endpoint - the owner of the per-device
|
||||
; page - may well be freed before this one, taking the page with it. The
|
||||
; authoritative pointer is the one in SlotPages: it is cleared when the slot
|
||||
; is released, so it can never point to freed memory.
|
||||
mov ecx, [ebx+xhci_pipe.SlotId]
|
||||
test ecx, ecx
|
||||
jz .drop_ring
|
||||
mov eax, [esi+xhci_controller.SlotPages-XCD+ecx*4]
|
||||
test eax, eax
|
||||
jz .drop_ring
|
||||
mov ecx, [ebx+xhci_pipe.DCI]
|
||||
cmp ecx, 32
|
||||
jae .drop_ring
|
||||
and dword [eax+XHCI_PIPES_OFS+ecx*4], 0
|
||||
.drop_ring:
|
||||
mov eax, [ebx+xhci_pipe.Ring]
|
||||
test eax, eax
|
||||
jz @f
|
||||
invoke KernelFree, eax
|
||||
and [ebx+xhci_pipe.Ring], 0
|
||||
@@:
|
||||
mov eax, [ebx+xhci_pipe.RingMap]
|
||||
test eax, eax
|
||||
jz .free
|
||||
invoke KernelFree, eax
|
||||
and [ebx+xhci_pipe.RingMap], 0
|
||||
.free:
|
||||
pop edi esi ebx
|
||||
mov eax, [ptr]
|
||||
sub eax, sizeof.xhci_pipe
|
||||
invoke usbhc_api.usb_free_common, eax
|
||||
ret
|
||||
endp
|
||||
|
||||
; Allocates the transfer ring of a pipe.
|
||||
; in: ebx -> xhci_pipe. out: eax = 0 on failure.
|
||||
proc xhci_alloc_ring
|
||||
push ecx edx
|
||||
call xhci_alloc_page
|
||||
test eax, eax
|
||||
jz .nothing
|
||||
mov [ebx+xhci_pipe.RingMap], eax
|
||||
call xhci_alloc_page
|
||||
test eax, eax
|
||||
jnz @f
|
||||
invoke KernelFree, [ebx+xhci_pipe.RingMap]
|
||||
and [ebx+xhci_pipe.RingMap], 0
|
||||
xor eax, eax
|
||||
jmp .nothing
|
||||
@@:
|
||||
mov [ebx+xhci_pipe.Ring], eax
|
||||
mov [ebx+xhci_pipe.RingPhys], edx
|
||||
; The last entry returns to the beginning of the ring and toggles the cycle.
|
||||
lea ecx, [eax+(XHCI_RING_TRBS-1)*16]
|
||||
mov [ecx], edx
|
||||
mov dword [ecx+12], (XHCI_TRB_LINK shl 10) + XHCI_TRB_TC
|
||||
and [ebx+xhci_pipe.Enqueue], 0
|
||||
and [ebx+xhci_pipe.Dequeue], 0
|
||||
and [ebx+xhci_pipe.Reserved], 0
|
||||
and [ebx+xhci_pipe.FirstFix], 0
|
||||
mov [ebx+xhci_pipe.Cycle], XHCI_TRB_C
|
||||
movi eax, 1
|
||||
.nothing:
|
||||
pop edx ecx
|
||||
ret
|
||||
endp
|
||||
|
||||
; Stores the pipe in the per-device table used by the event ring handler.
|
||||
; in: ebx -> xhci_pipe.
|
||||
proc xhci_register_pipe
|
||||
push eax ecx edx
|
||||
mov eax, [ebx+xhci_pipe.DevPage]
|
||||
test eax, eax
|
||||
jz @f
|
||||
mov ecx, [ebx+xhci_pipe.DCI]
|
||||
cmp ecx, 32
|
||||
jae @f
|
||||
lea edx, [ebx+sizeof.xhci_pipe]
|
||||
mov [eax+XHCI_PIPES_OFS+ecx*4], edx
|
||||
@@:
|
||||
pop edx ecx eax
|
||||
ret
|
||||
endp
|
||||
|
||||
; Computes the Interval field of the Endpoint Context of an interrupt endpoint.
|
||||
; The kernel passes bInterval from the endpoint descriptor: for high-speed
|
||||
; devices it is an exponent of 125 us periods, for low- and full-speed devices
|
||||
; it is a number of frames.
|
||||
; in: ebx -> xhci_pipe, eax = bInterval.
|
||||
proc xhci_calc_interval
|
||||
push eax ecx
|
||||
cmp [ebx+xhci_pipe.Speed], USB_SPEED_HS
|
||||
jnz .low_speed
|
||||
test eax, eax
|
||||
jz @f
|
||||
dec eax
|
||||
@@:
|
||||
jmp .clamp
|
||||
.low_speed:
|
||||
; One frame equals eight periods of 125 us, hence the offset of three.
|
||||
test eax, eax
|
||||
jnz @f
|
||||
movi eax, 1
|
||||
@@:
|
||||
bsr ecx, eax
|
||||
lea eax, [ecx+3]
|
||||
.clamp:
|
||||
cmp eax, 15
|
||||
jbe @f
|
||||
movi eax, 15
|
||||
@@:
|
||||
mov [ebx+xhci_pipe.Interval], eax
|
||||
pop ecx eax
|
||||
ret
|
||||
endp
|
||||
|
||||
; Called from usb_open_pipe.
|
||||
; in: edi -> usb_pipe for the target, ecx -> usb_pipe of the config pipe,
|
||||
; esi -> usb_controller, eax -> usb_gtd of the first descriptor,
|
||||
; [ebp+12] = endpoint, [ebp+16] = maxpacket, [ebp+20] = type,
|
||||
; [ebp+24] = interval.
|
||||
; out: eax = 0 on failure.
|
||||
proc xhci_init_pipe
|
||||
virtual at ebp+8
|
||||
.config_pipe dd ?
|
||||
.endpoint dd ?
|
||||
.maxpacket dd ?
|
||||
.type dd ?
|
||||
.interval dd ?
|
||||
end virtual
|
||||
push ebx
|
||||
sub edi, sizeof.xhci_pipe
|
||||
sub ecx, sizeof.xhci_pipe
|
||||
mov ebx, edi ; ebx -> xhci_pipe being initialized
|
||||
; 1. Copy the description of the device from the config pipe.
|
||||
mov eax, [ecx+xhci_pipe.SlotId]
|
||||
mov [ebx+xhci_pipe.SlotId], eax
|
||||
mov eax, [ecx+xhci_pipe.DevPage]
|
||||
mov [ebx+xhci_pipe.DevPage], eax
|
||||
mov eax, [ecx+xhci_pipe.DevPagePhys]
|
||||
mov [ebx+xhci_pipe.DevPagePhys], eax
|
||||
mov eax, [ecx+xhci_pipe.Speed]
|
||||
mov [ebx+xhci_pipe.Speed], eax
|
||||
mov eax, [ecx+xhci_pipe.RootPort]
|
||||
mov [ebx+xhci_pipe.RootPort], eax
|
||||
mov eax, [ecx+xhci_pipe.Route]
|
||||
mov [ebx+xhci_pipe.Route], eax
|
||||
mov eax, [ecx+xhci_pipe.Depth]
|
||||
mov [ebx+xhci_pipe.Depth], eax
|
||||
mov eax, [ecx+xhci_pipe.TTSlot]
|
||||
mov [ebx+xhci_pipe.TTSlot], eax
|
||||
mov eax, [ecx+xhci_pipe.TTPort]
|
||||
mov [ebx+xhci_pipe.TTPort], eax
|
||||
if XHCI_SUPERSPEED
|
||||
mov eax, [ecx+xhci_pipe.PSIV]
|
||||
mov [ebx+xhci_pipe.PSIV], eax
|
||||
end if
|
||||
; 2. Work out the Device Context Index and the endpoint type.
|
||||
mov eax, [.endpoint]
|
||||
test eax, eax
|
||||
jz .control_ep
|
||||
mov ecx, eax
|
||||
and ecx, 15
|
||||
add ecx, ecx
|
||||
test al, 80h
|
||||
jz @f
|
||||
inc ecx
|
||||
or [ebx+xhci_pipe.Flags], XHCI_PIPE_IN
|
||||
@@:
|
||||
mov [ebx+xhci_pipe.DCI], ecx
|
||||
mov eax, [.type]
|
||||
cmp eax, BULK_PIPE
|
||||
jz .bulk
|
||||
cmp eax, INTERRUPT_PIPE
|
||||
jz .interrupt
|
||||
; A control endpoint other than endpoint zero is unusual but legal.
|
||||
mov [ebx+xhci_pipe.EpType], XHCI_EP_CONTROL
|
||||
jmp .have_type
|
||||
.bulk:
|
||||
movi eax, XHCI_EP_BULK_OUT
|
||||
test [ebx+xhci_pipe.Flags], XHCI_PIPE_IN
|
||||
jz @f
|
||||
movi eax, XHCI_EP_BULK_IN
|
||||
@@:
|
||||
mov [ebx+xhci_pipe.EpType], eax
|
||||
jmp .have_type
|
||||
.interrupt:
|
||||
movi eax, XHCI_EP_INT_OUT
|
||||
test [ebx+xhci_pipe.Flags], XHCI_PIPE_IN
|
||||
jz @f
|
||||
movi eax, XHCI_EP_INT_IN
|
||||
@@:
|
||||
mov [ebx+xhci_pipe.EpType], eax
|
||||
mov eax, [.interval]
|
||||
call xhci_calc_interval
|
||||
.have_type:
|
||||
mov eax, [.maxpacket]
|
||||
mov [ebx+xhci_pipe.MaxPacket], eax
|
||||
if XHCI_SUPERSPEED
|
||||
call xhci_ss_get_burst
|
||||
end if
|
||||
jmp .alloc_ring
|
||||
.control_ep:
|
||||
; The default control endpoint always has index one. Until the real packet size
|
||||
; is known from the device descriptor, use the value the specification requires
|
||||
; for the speed of the device: the kernel asks for 64 regardless of the speed,
|
||||
; which is wrong for low- and full-speed devices.
|
||||
mov [ebx+xhci_pipe.DCI], 1
|
||||
mov [ebx+xhci_pipe.EpType], XHCI_EP_CONTROL
|
||||
movi eax, 64
|
||||
cmp [ebx+xhci_pipe.Speed], USB_SPEED_HS
|
||||
jz @f
|
||||
movi eax, 8
|
||||
@@:
|
||||
if XHCI_SUPERSPEED
|
||||
; A SuperSpeed device always uses 512 bytes on the default control endpoint.
|
||||
cmp [ebx+xhci_pipe.PSIV], XHCI_PSI_SS
|
||||
jb @f
|
||||
mov eax, 512
|
||||
@@:
|
||||
end if
|
||||
mov [ebx+xhci_pipe.MaxPacket], eax
|
||||
.alloc_ring:
|
||||
; 3. Allocate the transfer ring.
|
||||
call xhci_alloc_ring
|
||||
test eax, eax
|
||||
jz .fail
|
||||
; 4. Choose the software list the pipe belongs to and insert it there. The
|
||||
; hardware knows nothing about these lists; they exist only so that the kernel
|
||||
; can walk all pipes and reinsert an aborted one.
|
||||
lea edx, [esi+xhci_controller.ControlED-XCD]
|
||||
cmp [.type], BULK_PIPE
|
||||
jb @f
|
||||
lea edx, [esi+xhci_controller.BulkED-XCD]
|
||||
jz @f
|
||||
lea edx, [esi+xhci_controller.IntED-XCD]
|
||||
@@:
|
||||
lea edi, [ebx+sizeof.xhci_pipe]
|
||||
mov [edi+usb_pipe.BaseList], edx
|
||||
mov ecx, [edx+usb_pipe.NextVirt]
|
||||
mov [edi+usb_pipe.NextVirt], ecx
|
||||
mov [edi+usb_pipe.PrevVirt], edx
|
||||
mov [ecx+usb_pipe.PrevVirt], edi
|
||||
mov [edx+usb_pipe.NextVirt], edi
|
||||
; 5. Now do the hardware part.
|
||||
cmp [.endpoint], 0
|
||||
jz .address_device
|
||||
call xhci_register_pipe
|
||||
mov edi, [.config_pipe]
|
||||
sub edi, sizeof.xhci_pipe
|
||||
call xhci_configure_endpoint
|
||||
xhci_trace 'K : XHCI open pipe: slot %d dci %d\n', [ebx+xhci_pipe.SlotId], [ebx+xhci_pipe.DCI]
|
||||
cmp eax, XHCI_CC_SUCCESS
|
||||
jz .success
|
||||
DEBUGF 1,'K : XHCI: Configure Endpoint failed, code %d\n',eax
|
||||
jmp .unlink_fail
|
||||
.address_device:
|
||||
; 6. This is a new device: allocate its Device Context, publish the slot and
|
||||
; let the controller give the device a bus address.
|
||||
call xhci_alloc_page
|
||||
test eax, eax
|
||||
jz .unlink_fail
|
||||
mov [ebx+xhci_pipe.DevPage], eax
|
||||
mov [ebx+xhci_pipe.DevPagePhys], edx
|
||||
mov ecx, [ebx+xhci_pipe.SlotId]
|
||||
mov [esi+xhci_controller.SlotPages-XCD+ecx*4], eax
|
||||
call xhci_register_pipe
|
||||
call xhci_address_device
|
||||
test eax, eax
|
||||
jz .free_devpage
|
||||
.success:
|
||||
; usb_open_pipe keeps the pointer to the new pipe in edi across this call, so
|
||||
; it has to be handed back untouched; the branch above has overwritten it with
|
||||
; the pipe of the default control endpoint.
|
||||
lea edi, [ebx+sizeof.xhci_pipe]
|
||||
pop ebx
|
||||
movi eax, 1
|
||||
ret
|
||||
.free_devpage:
|
||||
mov ecx, [ebx+xhci_pipe.SlotId]
|
||||
and [esi+xhci_controller.SlotPages-XCD+ecx*4], 0
|
||||
mov eax, [ebx+xhci_pipe.DevPage]
|
||||
invoke KernelFree, eax
|
||||
and [ebx+xhci_pipe.DevPage], 0
|
||||
.unlink_fail:
|
||||
; Undo the insertion into the software list before failing.
|
||||
lea edi, [ebx+sizeof.xhci_pipe]
|
||||
mov eax, [edi+usb_pipe.NextVirt]
|
||||
mov edx, [edi+usb_pipe.PrevVirt]
|
||||
mov [eax+usb_pipe.PrevVirt], edx
|
||||
mov [edx+usb_pipe.NextVirt], eax
|
||||
.fail:
|
||||
lea edi, [ebx+sizeof.xhci_pipe]
|
||||
pop ebx
|
||||
xor eax, eax
|
||||
ret
|
||||
endp
|
||||
|
||||
; Removes the pipe from the hardware configuration of the device.
|
||||
; in: esi -> usb_controller, ebx -> usb_pipe.
|
||||
proc xhci_unlink_pipe
|
||||
pushad
|
||||
sub ebx, sizeof.xhci_pipe
|
||||
cmp [ebx+xhci_pipe.SlotId], 0
|
||||
jz .nothing
|
||||
cmp [ebx+xhci_pipe.DCI], 1
|
||||
jz .nothing ; the slot itself is released by FreePipe
|
||||
call xhci_ctrl_pipe
|
||||
test eax, eax
|
||||
jz .nothing
|
||||
mov edi, eax ; edi -> pipe of endpoint zero
|
||||
lea ecx, [esi+xhci_controller.CmdLock-XCD]
|
||||
invoke MutexLock
|
||||
call xhci_clear_input_ctx
|
||||
mov ecx, [ebx+xhci_pipe.DCI]
|
||||
movi eax, 1
|
||||
shl eax, cl
|
||||
mov edx, [esi+xhci_controller.InputCtx-XCD]
|
||||
mov [edx], eax ; drop this endpoint
|
||||
mov dword [edx+4], 1 ; keep the Slot Context
|
||||
mov ecx, [edi+xhci_pipe.MaxDCI]
|
||||
test ecx, ecx
|
||||
jnz @f
|
||||
movi ecx, 1
|
||||
@@:
|
||||
push ebx
|
||||
mov ebx, edi
|
||||
call xhci_fill_slot_ctx
|
||||
pop ebx
|
||||
mov edx, [ebx+xhci_pipe.SlotId]
|
||||
shl edx, 24
|
||||
or edx, XHCI_TRB_CONFIG_EP shl 10
|
||||
mov eax, [esi+xhci_controller.InputCtxPhys-XCD]
|
||||
xor ebx, ebx
|
||||
xor ecx, ecx
|
||||
call xhci_cmd_submit
|
||||
lea ecx, [esi+xhci_controller.CmdLock-XCD]
|
||||
invoke MutexUnlock
|
||||
.nothing:
|
||||
popad
|
||||
ret
|
||||
endp
|
||||
|
||||
; Temporarily removes the pipe from the hardware schedule.
|
||||
; in: esi -> usb_controller, ebx -> usb_pipe.
|
||||
proc xhci_disable_pipe
|
||||
pushad
|
||||
sub ebx, sizeof.xhci_pipe
|
||||
cmp [ebx+xhci_pipe.SlotId], 0
|
||||
jz .nothing
|
||||
mov ecx, [ebx+xhci_pipe.DCI]
|
||||
shl ecx, 16
|
||||
mov edx, [ebx+xhci_pipe.SlotId]
|
||||
shl edx, 24
|
||||
or edx, ecx
|
||||
or edx, XHCI_TRB_STOP_EP shl 10
|
||||
xor eax, eax
|
||||
xor ebx, ebx
|
||||
xor ecx, ecx
|
||||
call xhci_cmd_sync
|
||||
.nothing:
|
||||
popad
|
||||
ret
|
||||
endp
|
||||
|
||||
; Reinserts the pipe into the hardware schedule after xhci_disable_pipe, with
|
||||
; an empty transfer queue.
|
||||
; in: esi -> usb_controller, ebx -> usb_pipe,
|
||||
; edx -> current descriptor, eax -> new last descriptor.
|
||||
proc xhci_enable_pipe
|
||||
pushad
|
||||
sub ebx, sizeof.xhci_pipe
|
||||
mov eax, [ebx+xhci_pipe.Ring]
|
||||
test eax, eax
|
||||
jz .nothing
|
||||
; The queue is empty now, so the ring can be restarted from its beginning.
|
||||
mov edi, eax
|
||||
xor eax, eax
|
||||
mov ecx, 0x1000/4
|
||||
rep stosd
|
||||
mov edi, [ebx+xhci_pipe.RingMap]
|
||||
mov ecx, 0x1000/4
|
||||
rep stosd
|
||||
mov edi, [ebx+xhci_pipe.Ring]
|
||||
add edi, (XHCI_RING_TRBS-1)*16
|
||||
mov eax, [ebx+xhci_pipe.RingPhys]
|
||||
mov [edi], eax
|
||||
mov dword [edi+12], (XHCI_TRB_LINK shl 10) + XHCI_TRB_TC
|
||||
and [ebx+xhci_pipe.Enqueue], 0
|
||||
and [ebx+xhci_pipe.Dequeue], 0
|
||||
and [ebx+xhci_pipe.Reserved], 0
|
||||
and [ebx+xhci_pipe.FirstFix], 0
|
||||
mov [ebx+xhci_pipe.Cycle], XHCI_TRB_C
|
||||
call xhci_set_dequeue
|
||||
.nothing:
|
||||
popad
|
||||
ret
|
||||
endp
|
||||
|
||||
; =============================================================================
|
||||
; ========================== Address and packet size ==========================
|
||||
; =============================================================================
|
||||
|
||||
; Called from usb_set_address_callback. The bus address is chosen by the
|
||||
; controller itself while executing the Address Device command, so the only
|
||||
; thing left to do is to remember the number the kernel has reserved: it asks
|
||||
; for it back on disconnect in order to mark it free again.
|
||||
; in: esi -> usb_controller, ebx -> usb_pipe, cl = address.
|
||||
proc xhci_set_device_address
|
||||
movzx eax, cl
|
||||
mov [ebx+xhci_pipe.Address-sizeof.xhci_pipe], eax
|
||||
jmp [usbhc_api.usb_subscribe_control]
|
||||
endp
|
||||
|
||||
; in: esi -> usb_controller, ebx -> usb_pipe. out: eax = address.
|
||||
proc xhci_get_device_address
|
||||
mov eax, [ebx+xhci_pipe.Address-sizeof.xhci_pipe]
|
||||
ret
|
||||
endp
|
||||
|
||||
; Called from usb_get_descr8_callback once the real packet size of the default
|
||||
; control endpoint is known. On xHCI that value lives in the Endpoint Context,
|
||||
; so an Evaluate Context command is needed to update it.
|
||||
; in: esi -> usb_controller, ebx -> usb_pipe, ecx = packet size.
|
||||
proc xhci_set_endpoint_packet_size
|
||||
push ebx ecx edx edi
|
||||
sub ebx, sizeof.xhci_pipe
|
||||
if XHCI_SUPERSPEED
|
||||
; For a SuperSpeed device bMaxPacketSize0 is an exponent, and the only value
|
||||
; the specification allows is 9: use 512 directly instead of the raw byte.
|
||||
cmp [ebx+xhci_pipe.PSIV], XHCI_PSI_SS
|
||||
jb @f
|
||||
mov ecx, 512
|
||||
@@:
|
||||
end if
|
||||
mov [ebx+xhci_pipe.MaxPacket], ecx
|
||||
lea ecx, [esi+xhci_controller.CmdLock-XCD]
|
||||
invoke MutexLock
|
||||
call xhci_clear_input_ctx
|
||||
mov edx, [esi+xhci_controller.InputCtx-XCD]
|
||||
mov dword [edx+4], 2 ; evaluate the default control endpoint
|
||||
call xhci_fill_ep_ctx
|
||||
mov edx, [ebx+xhci_pipe.SlotId]
|
||||
shl edx, 24
|
||||
or edx, XHCI_TRB_EVAL_CTX shl 10
|
||||
mov eax, [esi+xhci_controller.InputCtxPhys-XCD]
|
||||
push ebx
|
||||
xor ebx, ebx
|
||||
xor ecx, ecx
|
||||
call xhci_cmd_submit
|
||||
pop ebx
|
||||
cmp eax, XHCI_CC_SUCCESS
|
||||
jz @f
|
||||
DEBUGF 1,'K : XHCI: Evaluate Context failed, code %d\n',eax
|
||||
@@:
|
||||
lea ecx, [esi+xhci_controller.CmdLock-XCD]
|
||||
invoke MutexUnlock
|
||||
pop edi edx ecx ebx
|
||||
jmp [usbhc_api.usb_subscribe_control]
|
||||
endp
|
||||
|
||||
; If the descriptor that has just completed is the answer to a request for the
|
||||
; hub descriptor, tell the controller that the device is a hub: it has to know
|
||||
; that in order to serve the devices behind it.
|
||||
; in: ebx -> usb_gtd.
|
||||
proc xhci_check_hub_descriptor
|
||||
pushad
|
||||
cmp [ebx+usb_gtd.Callback], 0
|
||||
jz .nothing
|
||||
mov eax, [ebx+usb_gtd.Pipe]
|
||||
mov esi, [eax+usb_pipe.Controller]
|
||||
sub eax, sizeof.xhci_pipe
|
||||
test [eax+xhci_pipe.Flags], XHCI_PIPE_HUBPEND
|
||||
jz .nothing
|
||||
and [eax+xhci_pipe.Flags], not XHCI_PIPE_HUBPEND
|
||||
cmp [ebx+xhci_gtd.Status-sizeof.xhci_gtd], XHCI_CC_SUCCESS
|
||||
jnz .nothing
|
||||
mov edx, [eax+xhci_pipe.HubBuf]
|
||||
test edx, edx
|
||||
jz .nothing
|
||||
cmp byte [edx+1], 29h ; bDescriptorType
|
||||
jnz .nothing
|
||||
or [eax+xhci_pipe.Flags], XHCI_PIPE_ISHUB
|
||||
mov ebx, eax ; ebx -> xhci_pipe of the hub
|
||||
movzx edi, byte [edx+2] ; bNbrPorts
|
||||
movzx ebp, byte [edx+3] ; low byte of wHubCharacteristics
|
||||
shr ebp, 5
|
||||
and ebp, 3 ; Transaction Translator Think Time
|
||||
DEBUGF 1,'K : XHCI: device on slot %d is a hub with %d ports\n',[ebx+xhci_pipe.SlotId],edi
|
||||
lea ecx, [esi+xhci_controller.CmdLock-XCD]
|
||||
invoke MutexLock
|
||||
call xhci_clear_input_ctx
|
||||
mov eax, [esi+xhci_controller.InputCtx-XCD]
|
||||
mov dword [eax+4], 1 ; only the Slot Context is evaluated
|
||||
mov ecx, [ebx+xhci_pipe.MaxDCI]
|
||||
test ecx, ecx
|
||||
jnz @f
|
||||
movi ecx, 1
|
||||
@@:
|
||||
call xhci_fill_slot_ctx
|
||||
; Patch the Slot Context with the fields that describe a hub. Only Configure
|
||||
; Endpoint takes them into account, Evaluate Context would ignore them.
|
||||
mov eax, [esi+xhci_controller.InputCtx-XCD]
|
||||
movi ecx, 1
|
||||
call xhci_context
|
||||
or dword [eax], 1 shl 26 ; this device is a hub
|
||||
cmp [ebx+xhci_pipe.Speed], USB_SPEED_HS
|
||||
jnz @f
|
||||
shl ebp, 16
|
||||
or [eax+8], ebp
|
||||
@@:
|
||||
shl edi, 24
|
||||
or [eax+4], edi ; Number of Ports
|
||||
mov edx, [ebx+xhci_pipe.SlotId]
|
||||
shl edx, 24
|
||||
or edx, XHCI_TRB_CONFIG_EP shl 10
|
||||
mov eax, [esi+xhci_controller.InputCtxPhys-XCD]
|
||||
xor ebx, ebx
|
||||
xor ecx, ecx
|
||||
call xhci_cmd_submit
|
||||
cmp eax, XHCI_CC_SUCCESS
|
||||
jz @f
|
||||
DEBUGF 1,'K : XHCI: cannot mark the device as a hub, code %d\n',eax
|
||||
@@:
|
||||
lea ecx, [esi+xhci_controller.CmdLock-XCD]
|
||||
invoke MutexUnlock
|
||||
.nothing:
|
||||
popad
|
||||
ret
|
||||
endp
|
||||
@@ -1,135 +0,0 @@
|
||||
; SuperSpeed support for the xHCI driver, included from xhci.asm when
|
||||
; XHCI_SUPERSPEED is enabled. The pieces too small to live here - the port
|
||||
; map, the Slot Context speed, the 512-byte default control endpoint, the
|
||||
; Max Burst field of the Endpoint Context - sit in the other files under
|
||||
; "if XHCI_SUPERSPEED" guards; this file keeps the self-contained procedures.
|
||||
;
|
||||
; The kernel USB stack knows nothing about SuperSpeed, so it never learns
|
||||
; about it: a SuperSpeed device is announced as a high-speed one, which also
|
||||
; keeps the Transaction Translator logic away from it. The raw PORTSC speed
|
||||
; identifier travels in xhci_pipe.PSIV instead and reaches everything that
|
||||
; really needs it. SuperSpeed hubs are not supported: the kernel only speaks
|
||||
; the USB2 hub protocol, so a device behind a USB3 hub is served by the USB2
|
||||
; half of that hub at high speed.
|
||||
|
||||
; =============================================================================
|
||||
; ============================ SuperSpeed ports ===============================
|
||||
; =============================================================================
|
||||
|
||||
; Called from xhci_new_port for a SuperSpeed root port instead of the USB2
|
||||
; reset entry point: a SuperSpeed link trains itself and the port enables
|
||||
; itself on connect, reporting the speed with no reset at all. When the link
|
||||
; is already up, skip straight to the reset recovery stage, after which
|
||||
; xhci_port_init picks the device up; otherwise try a warm reset.
|
||||
; in: esi -> usb_controller, ecx = port index.
|
||||
proc xhci_ss_start_port
|
||||
push eax edx
|
||||
and [esi+usb_controller.ResettingHub], 0
|
||||
mov [esi+usb_controller.ResettingPort], cl
|
||||
push ecx
|
||||
invoke GetTimerTicks
|
||||
pop ecx
|
||||
mov [esi+usb_controller.ResetTime], eax
|
||||
mov [esi+xhci_controller.ResetStart-XCD], eax
|
||||
call xhci_port_reg
|
||||
mov eax, [edx]
|
||||
test al, XHCI_PORT_PED
|
||||
jz .warm_reset
|
||||
mov [esi+usb_controller.ResettingStatus], 2
|
||||
DEBUGF 1,'K : XHCI %x: SS port %d link is up, PORTSC=%x\n',esi,ecx,eax
|
||||
jmp .nothing
|
||||
.warm_reset:
|
||||
; Connected, but the link has not come up. The Port Reset bit is set while a
|
||||
; warm reset is running, so the ordinary reset-wait machinery in
|
||||
; xhci_port_reset_done serves this case unchanged; the extra WRC change bit is
|
||||
; acknowledged there together with the usual ones.
|
||||
mov dword [edx], XHCI_PORT_PP + XHCI_PORT_WPR
|
||||
mov [esi+usb_controller.ResettingStatus], 1
|
||||
DEBUGF 1,'K : XHCI %x: warm-resetting port %d, PORTSC=%x\n',esi,ecx,eax
|
||||
.nothing:
|
||||
pop edx eax
|
||||
ret
|
||||
endp
|
||||
|
||||
; The kernel restarts pending root ports through the NewPortReset entry of
|
||||
; usb_hardware_func directly, bypassing xhci_new_port; SuperSpeed ports must
|
||||
; not get the USB2 reset on that path either, so the entry points here.
|
||||
; in: esi -> usb_controller, ecx = port index.
|
||||
proc xhci_ss_port_reset
|
||||
bt [esi+xhci_controller.SSPortMask-XCD], ecx
|
||||
jnc xhci_new_port.reset
|
||||
call xhci_ss_start_port
|
||||
ret
|
||||
endp
|
||||
|
||||
; =============================================================================
|
||||
; ===================== Endpoint Companion descriptors ========================
|
||||
; =============================================================================
|
||||
|
||||
; Reads the SuperSpeed Endpoint Companion descriptor of a bulk endpoint and
|
||||
; keeps its bMaxBurst for the Endpoint Context, allowing bursts of up to
|
||||
; bMaxBurst+1 packets per transaction. Zero (no bursts) is always legal, so
|
||||
; any failure just leaves the field alone. Only bulk endpoints are considered:
|
||||
; a nonzero burst on a periodic endpoint would also require the Max ESIT
|
||||
; Payload fields, and real interrupt endpoints do not burst anyway.
|
||||
; Relies on the stack frame of usb_open_pipe exactly like xhci_init_pipe does:
|
||||
; [ebp+8] is the config pipe of the device.
|
||||
; in: ebx -> xhci_pipe of a non-control endpoint being opened.
|
||||
proc xhci_ss_get_burst
|
||||
push eax ecx edx edi
|
||||
; 1. Only SuperSpeed bulk endpoints are of interest.
|
||||
cmp [ebx+xhci_pipe.PSIV], XHCI_PSI_SS
|
||||
jb .nothing
|
||||
mov eax, [ebx+xhci_pipe.EpType]
|
||||
and al, 3
|
||||
cmp al, 2 ; bulk endpoint types are 2 and 6
|
||||
jnz .nothing
|
||||
; 2. Find the configuration data kept by the kernel behind the device
|
||||
; descriptor; it holds the endpoint descriptors with their companions.
|
||||
mov eax, [ebp+8]
|
||||
mov eax, [eax+usb_pipe.DeviceData]
|
||||
test eax, eax
|
||||
jz .nothing
|
||||
movzx edx, [eax+usb_device_data.DeviceDescrSize]
|
||||
mov edi, [eax+usb_device_data.ConfigDataSize]
|
||||
lea ecx, [eax+edx+usb_device_data.DeviceDescriptor]
|
||||
add edi, ecx ; edi -> end of the configuration data
|
||||
; 3. Reconstruct bEndpointAddress from the Device Context Index.
|
||||
mov edx, [ebx+xhci_pipe.DCI]
|
||||
shr edx, 1
|
||||
test [ebx+xhci_pipe.Flags], XHCI_PIPE_IN
|
||||
jz @f
|
||||
or dl, 80h
|
||||
@@:
|
||||
; 4. Walk the descriptors to the one of this endpoint.
|
||||
.walk:
|
||||
lea eax, [ecx+2]
|
||||
cmp eax, edi
|
||||
ja .nothing
|
||||
movzx eax, byte [ecx] ; bLength
|
||||
test eax, eax
|
||||
jz .nothing ; malformed data, stop
|
||||
cmp byte [ecx+1], 5 ; an endpoint descriptor?
|
||||
jnz .advance
|
||||
cmp [ecx+2], dl ; bEndpointAddress
|
||||
jnz .advance
|
||||
; 5. The companion descriptor (type 30h) immediately follows its endpoint.
|
||||
add ecx, eax
|
||||
lea eax, [ecx+3]
|
||||
cmp eax, edi
|
||||
ja .nothing
|
||||
cmp byte [ecx+1], 30h ; SuperSpeed Endpoint Companion
|
||||
jnz .nothing
|
||||
movzx eax, byte [ecx+2] ; bMaxBurst
|
||||
cmp eax, 15
|
||||
ja .nothing
|
||||
mov [ebx+xhci_pipe.MaxBurst], eax
|
||||
DEBUGF 1,'K : XHCI: slot %d dci %d bursts %d+1 packets\n',[ebx+xhci_pipe.SlotId],[ebx+xhci_pipe.DCI],eax
|
||||
jmp .nothing
|
||||
.advance:
|
||||
add ecx, eax
|
||||
jmp .walk
|
||||
.nothing:
|
||||
pop edi edx ecx eax
|
||||
ret
|
||||
endp
|
||||
File diff suppressed because it is too large.
Load diff
@@ -1721,8 +1721,7 @@ endp
|
||||
; out: eax = 1 if the interrupt came from this controller, 0 otherwise
|
||||
align 4
|
||||
ahci_irq_handler:
|
||||
push ebx esi edi
|
||||
mov esi, [esp + 12 + 4]
|
||||
mov esi, [esp + 4]
|
||||
test esi, esi
|
||||
jz .not_our
|
||||
mov edx, [esi + AHCI_CTR.abar]
|
||||
@@ -1787,11 +1786,9 @@ ahci_irq_handler:
|
||||
@@:
|
||||
pop eax
|
||||
mov eax, 1
|
||||
pop edi esi ebx
|
||||
ret
|
||||
.not_our:
|
||||
xor eax, eax
|
||||
pop edi esi ebx
|
||||
ret
|
||||
|
||||
|
||||
|
||||
@@ -1489,31 +1489,19 @@ dyndisk_handler:
|
||||
; 12. The fs operation has specified some partition.
|
||||
push edx ecx
|
||||
xor eax, eax
|
||||
mov ecx, eax
|
||||
lodsb
|
||||
@@:
|
||||
lea ecx, [ecx*4 + ecx]
|
||||
shl ecx, 1
|
||||
|
||||
sub eax, '0'
|
||||
jb .dyndisk_cleanup
|
||||
jz .dyndisk_cleanup
|
||||
cmp eax, 10
|
||||
jnc .dyndisk_cleanup
|
||||
|
||||
add ecx, eax
|
||||
cmp ecx, MAX_NUM_PARTITIONS
|
||||
ja .dyndisk_cleanup
|
||||
|
||||
mov ecx, eax
|
||||
lodsb
|
||||
cmp eax, '/'
|
||||
jz @f
|
||||
test eax, eax
|
||||
jnz @b
|
||||
jnz .dyndisk_cleanup
|
||||
dec esi
|
||||
@@:
|
||||
test ecx, ecx
|
||||
jz .dyndisk_cleanup
|
||||
|
||||
cmp byte [esi], 0
|
||||
jnz @f
|
||||
; partition info
|
||||
|
||||
@@ -2507,7 +2507,7 @@ dword-значение цвета 0x00RRGGBB
|
||||
* иначе eax = TID - идентификатор потока
|
||||
|
||||
---------------------- Константы для регистров: ----------------------
|
||||
eax - SF_THREAD_CONTROL (51) /
|
||||
eax - SF_CREATE_THREAD (51) /
|
||||
ebx - SSF_CREATE_THREAD (1), SSF_GET_CURR_THREAD_SLOT (2),
|
||||
SSF_GET_THREAD_PRIORITY (3), SSF_SET_THREAD_PRIORITY (4)
|
||||
|
||||
@@ -4098,9 +4098,6 @@ Architecture Software Developer's Manual, Volume 3, Appendix B);
|
||||
* подфункция 7 - запуск программы
|
||||
* подфункция 8 - удаление файла/папки
|
||||
* подфункция 9 - создание папки
|
||||
* подфункция 10 - переименование/перемещение
|
||||
* подфункция 11 - создание симлинка
|
||||
* подфункция 12 - чтение симлинка
|
||||
Для CD-приводов в связи с аппаратными ограничениями доступны
|
||||
только подфункции 0,1,5 и 7, вызов других подфункций завершится
|
||||
ошибкой с кодом 2.
|
||||
@@ -4115,8 +4112,7 @@ Architecture Software Developer's Manual, Volume 3, Appendix B);
|
||||
[ebx] - SSF_READ_FILE (0), SSF_READ_FOLDER (1), SSF_CREATE_FILE (2),
|
||||
SSF_WRITE_FILE (3), SSF_SET_END (4), SSF_GET_INFO (5),
|
||||
SSF_SET_INFO (6), SSF_START_APP (7), SSF_DELETE (8),
|
||||
SSF_CREATE_FOLDER (9), SSF_RENAME (10), SSF_CREATE_SYMLINK (11),
|
||||
SSF_READ_SYMLINK (12)
|
||||
SSF_CREATE_FOLDER (9)
|
||||
======================================================================
|
||||
= Функция 70, подфункция 0 - чтение файла с поддержкой длинных имён. =
|
||||
======================================================================
|
||||
@@ -4468,62 +4464,6 @@ Architecture Software Developer's Manual, Volume 3, Appendix B);
|
||||
* Формирование нового пути отличается от общих правил:
|
||||
относительный путь относится к папке целевого файла (или папки),
|
||||
абсолютный путь считается от корня раздела.
|
||||
|
||||
---------------------- Константы для регистров: ----------------------
|
||||
eax - SF_FILE (70)
|
||||
[ebx] - SSF_RENAME (10)
|
||||
======================================================================
|
||||
=========== Функция 70, подфункция 11 - создание симлинка. ===========
|
||||
======================================================================
|
||||
Параметры:
|
||||
* eax = 70 - номер функции
|
||||
* ebx = указатель на информационную структуру
|
||||
Формат информационной структуры:
|
||||
* +0: dword: 11 = номер подфункции
|
||||
* +4: dword: 0 (зарезервировано)
|
||||
* +8: dword: 0 (зарезервировано)
|
||||
* +12 = +0xC: dword: 0 (зарезервировано)
|
||||
* +16 = +0x10: dword: указатель на строку с целевым путём
|
||||
* +20 = +0x14: путь, правила формирования имён указаны в общем
|
||||
описании (путь ссылки)
|
||||
Возвращаемое значение:
|
||||
* eax = 0 - успешно, иначе код ошибки файловой системы
|
||||
* ebx разрушается
|
||||
Замечания:
|
||||
* Родительская папка должна существовать.
|
||||
* Для CD функция не поддерживается (возвращает код ошибки 2).
|
||||
|
||||
---------------------- Константы для регистров: ----------------------
|
||||
eax - SF_FILE (70)
|
||||
[ebx] - SSF_CREATE_SYMLINK (11)
|
||||
======================================================================
|
||||
============ Функция 70, подфункция 12 - чтение симлинка. ============
|
||||
======================================================================
|
||||
Параметры:
|
||||
* eax = 70 - номер функции
|
||||
* ebx = указатель на информационную структуру
|
||||
Формат информационной структуры:
|
||||
* +0: dword: 12 = номер подфункции
|
||||
* +4: dword: 0 (зарезервировано)
|
||||
* +8: dword: 0 (зарезервировано)
|
||||
* +12 = +0xC: dword: размер буфера в байтах
|
||||
* +16 = +0x10: dword: указатель на буфер для целевого пути
|
||||
* +20 = +0x14: путь, правила формирования имён указаны в общем
|
||||
описании (путь ссылки)
|
||||
Возвращаемое значение:
|
||||
* eax = 0 - успешно, иначе код ошибки файловой системы
|
||||
* ebx = число байт, записанных в буфер
|
||||
Замечания:
|
||||
* Функция не следует по симлинку; она читает целевой путь,
|
||||
на который указывает симлинк.
|
||||
* Целевой путь всегда завершается нулём, в том числе при обрезании;
|
||||
записывается не более (размер буфера - 1) байт пути.
|
||||
* Значение в ebx включает завершающий 0, как в подфункции 2
|
||||
функции 30.
|
||||
|
||||
---------------------- Константы для регистров: ----------------------
|
||||
eax - SF_FILE (70)
|
||||
[ebx] - SSF_READ_SYMLINK (12)
|
||||
======================================================================
|
||||
========== Функция 71 - установить заголовок окна программы ==========
|
||||
======================================================================
|
||||
@@ -5119,8 +5059,8 @@ Architecture Software Developer's Manual, Volume 3, Appendix B);
|
||||
* eax = дескриптор фьютекса, 0 при ошибке
|
||||
|
||||
---------------------- Константы для регистров: ----------------------
|
||||
eax - SF_POSIX (77)
|
||||
ebx - SSF_FUTEX_CREATE (0)
|
||||
eax - SF_FUTEX (77)
|
||||
ebx - SSF_CREATE (0)
|
||||
======================================================================
|
||||
============= Функция 77, подфункция 1, Удалить фьютекс. =============
|
||||
======================================================================
|
||||
@@ -5134,8 +5074,8 @@ Architecture Software Developer's Manual, Volume 3, Appendix B);
|
||||
* Ядро автоматически удаляет фьютексы при завершении процесса.
|
||||
|
||||
---------------------- Константы для регистров: ----------------------
|
||||
eax - SF_POSIX (77)
|
||||
ebx - SSF_FUTEX_DESTROY (1)
|
||||
eax - SF_FUTEX (77)
|
||||
ebx - SSF_DESTROY (1)
|
||||
======================================================================
|
||||
================= Функция 77, подфункция 2, Ожидать. =================
|
||||
======================================================================
|
||||
@@ -5151,8 +5091,8 @@ Architecture Software Developer's Manual, Volume 3, Appendix B);
|
||||
-2 - контрольное значение фьютекса не соответствует
|
||||
|
||||
---------------------- Константы для регистров: ----------------------
|
||||
eax - SF_POSIX (77)
|
||||
ebx - SSF_FUTEX_WAIT (2)
|
||||
eax - SF_FUTEX (77)
|
||||
ebx - SSF_WAIT (2)
|
||||
======================================================================
|
||||
================ Функция 77, подфункция 3, Разбудить. ================
|
||||
======================================================================
|
||||
@@ -5165,8 +5105,8 @@ Architecture Software Developer's Manual, Volume 3, Appendix B);
|
||||
* eax = количество разбуженых
|
||||
|
||||
---------------------- Константы для регистров: ----------------------
|
||||
eax - SF_POSIX (77)
|
||||
ebx - SSF_FUTEX_WAKE (3)
|
||||
eax - SF_FUTEX (77)
|
||||
ebx - SSF_WAKE (3)
|
||||
======================================================================
|
||||
Замечания:
|
||||
* Подфункции 4-7 зарезервированы и сейчас возвращают -1.
|
||||
@@ -5188,8 +5128,8 @@ Architecture Software Developer's Manual, Volume 3, Appendix B);
|
||||
* Поддерживаются только pipe-дескрипторы.
|
||||
|
||||
---------------------- Константы для регистров: ----------------------
|
||||
eax - SF_POSIX (77)
|
||||
ebx - SSF_FD_READ (10)
|
||||
eax - SF_FUTEX (77)
|
||||
ebx - SSF_FILE_READ (10)
|
||||
|
||||
======================================================================
|
||||
======== Функция 77, подфункция 11, Записать из буфера в файл. =======
|
||||
@@ -5208,8 +5148,8 @@ Architecture Software Developer's Manual, Volume 3, Appendix B);
|
||||
* Поддерживаются только pipe-дескрипторы.
|
||||
|
||||
---------------------- Константы для регистров: ----------------------
|
||||
eax - SF_POSIX (77)
|
||||
ebx - SSF_FD_WRITE (11)
|
||||
eax - SF_FUTEX (77)
|
||||
ebx - SSF_FILE_WRITE (11)
|
||||
|
||||
======================================================================
|
||||
=========== Функция 77, подфункция 13, Создать новый pipe. ===========
|
||||
@@ -5233,8 +5173,8 @@ Architecture Software Developer's Manual, Volume 3, Appendix B);
|
||||
- дескриптором записи.
|
||||
|
||||
---------------------- Константы для регистров: ----------------------
|
||||
eax - SF_POSIX (77)
|
||||
ebx - SSF_FD_PIPE2 (13)
|
||||
eax - SF_FUTEX (77)
|
||||
ebx - SSF_PIPE_CREATE (13)
|
||||
|
||||
======================================================================
|
||||
========== Функция -1 - завершить выполнение потока/процесса =========
|
||||
|
||||
@@ -2492,7 +2492,7 @@ Returned value:
|
||||
* otherwise eax = TID - thread identifier
|
||||
|
||||
---------------------- Constants for registers: ----------------------
|
||||
eax - SF_THREAD_CONTROL (51)
|
||||
eax - SF_CREATE_THREAD (51)
|
||||
ebx - SSF_CREATE_THREAD (1), SSF_GET_CURR_THREAD_SLOT (2),
|
||||
SSF_GET_THREAD_PRIORITY (3), SSF_SET_THREAD_PRIORITY (4)
|
||||
======================================================================
|
||||
@@ -4060,9 +4060,6 @@ Available subfunctions:
|
||||
* subfunction 7 - start application
|
||||
* subfunction 8 - delete file/folder
|
||||
* subfunction 9 - create folder
|
||||
* subfunction 10 - rename/move
|
||||
* subfunction 11 - create symlink
|
||||
* subfunction 12 - read symlink
|
||||
For CD-drives due to hardware limitations only subfunctions
|
||||
0,1,5 and 7 are available, other subfunctions return error
|
||||
with code 2.
|
||||
@@ -4076,8 +4073,7 @@ is called for corresponding device.
|
||||
[ebx] - SSF_READ_FILE (0), SSF_READ_FOLDER (1), SSF_CREATE_FILE (2),
|
||||
SSF_WRITE_FILE (3), SSF_SET_END (4), SSF_GET_INFO (5),
|
||||
SSF_SET_INFO (6), SSF_START_APP (7), SSF_DELETE (8),
|
||||
SSF_CREATE_FOLDER (9), SSF_RENAME (10), SSF_CREATE_SYMLINK (11),
|
||||
SSF_READ_SYMLINK (12)
|
||||
SSF_CREATE_FOLDER (9)
|
||||
======================================================================
|
||||
=== Function 70, subfunction 0 - read file with long names support. ==
|
||||
======================================================================
|
||||
@@ -4427,60 +4423,6 @@ Remarks:
|
||||
* New path forming differs from general rules:
|
||||
relative path relates to the target's parent folder,
|
||||
absolute path relates to the partition's root folder.
|
||||
|
||||
---------------------- Constants for registers: ----------------------
|
||||
eax - SF_FILE (70)
|
||||
[ebx] - SSF_RENAME (10)
|
||||
======================================================================
|
||||
=========== Function 70, subfunction 11 - create symlink. ============
|
||||
======================================================================
|
||||
Parameters:
|
||||
* eax = 70 - function number
|
||||
* ebx = pointer to the information structure
|
||||
Format of the information structure:
|
||||
* +0: dword: 11 = subfunction number
|
||||
* +4: dword: 0 (reserved)
|
||||
* +8: dword: 0 (reserved)
|
||||
* +12 = +0xC: dword: 0 (reserved)
|
||||
* +16 = +0x10: dword: pointer to the target path string
|
||||
* +20 = +0x14: path, general rules of names forming (link path)
|
||||
Returned value:
|
||||
* eax = 0 - success, otherwise file system error code
|
||||
* ebx destroyed
|
||||
Remarks:
|
||||
* The parent folder must already exist.
|
||||
* The function is not supported for CD (returns error code 2).
|
||||
|
||||
---------------------- Constants for registers: ----------------------
|
||||
eax - SF_FILE (70)
|
||||
[ebx] - SSF_CREATE_SYMLINK (11)
|
||||
======================================================================
|
||||
============ Function 70, subfunction 12 - read symlink. =============
|
||||
======================================================================
|
||||
Parameters:
|
||||
* eax = 70 - function number
|
||||
* ebx = pointer to the information structure
|
||||
Format of the information structure:
|
||||
* +0: dword: 12 = subfunction number
|
||||
* +4: dword: 0 (reserved)
|
||||
* +8: dword: 0 (reserved)
|
||||
* +12 = +0xC: dword: buffer size in bytes
|
||||
* +16 = +0x10: dword: pointer to buffer for target path
|
||||
* +20 = +0x14: path, general rules of names forming (link path)
|
||||
Returned value:
|
||||
* eax = 0 - success, otherwise file system error code
|
||||
* ebx = number of bytes written to the buffer
|
||||
Remarks:
|
||||
* The function does not follow the symlink; it reads the target path
|
||||
that the symlink points to.
|
||||
* The target path is always terminated with 0, even when truncated;
|
||||
at most (buffer size - 1) path bytes are written.
|
||||
* The value returned in ebx includes the terminating 0, as in
|
||||
subfunction 2 of function 30.
|
||||
|
||||
---------------------- Constants for registers: ----------------------
|
||||
eax - SF_FILE (70)
|
||||
[ebx] - SSF_READ_SYMLINK (12)
|
||||
======================================================================
|
||||
================== Function 71 - set window caption ==================
|
||||
======================================================================
|
||||
@@ -5331,8 +5273,8 @@ Returned value:
|
||||
* eax = futex handle, 0 on error
|
||||
|
||||
---------------------- Constants for registers: ----------------------
|
||||
eax - SF_POSIX (77)
|
||||
ebx - SSF_FUTEX_CREATE (0)
|
||||
eax - SF_FUTEX (77)
|
||||
ebx - SSF_CREATE (0)
|
||||
======================================================================
|
||||
========= Function 77, Subfunction 1, Destroy futex object ===========
|
||||
======================================================================
|
||||
@@ -5347,8 +5289,8 @@ Remarks:
|
||||
terminates.
|
||||
|
||||
---------------------- Constants for registers: ----------------------
|
||||
eax - SF_POSIX (77)
|
||||
ebx - SSF_FUTEX_DESTROY (1)
|
||||
eax - SF_FUTEX (77)
|
||||
ebx - SSF_DESTROY (1)
|
||||
======================================================================
|
||||
=============== Function 77, Subfunction 2, Futex wait ===============
|
||||
======================================================================
|
||||
@@ -5364,8 +5306,8 @@ Returned value:
|
||||
-2 - futex control value doesn't match
|
||||
|
||||
---------------------- Constants for registers: ----------------------
|
||||
eax - SF_POSIX (77)
|
||||
ebx - SSF_FUTEX_WAIT (2)
|
||||
eax - SF_FUTEX (77)
|
||||
ebx - SSF_WAIT (2)
|
||||
======================================================================
|
||||
=============== Function 77, Subfunction 3, Futex wake ===============
|
||||
======================================================================
|
||||
@@ -5378,8 +5320,8 @@ Returned value:
|
||||
* eax = number of waiters that were woken up
|
||||
|
||||
---------------------- Constants for registers: ----------------------
|
||||
eax - SF_POSIX (77)
|
||||
ebx - SSF_FUTEX_WAKE (3)
|
||||
eax - SF_FUTEX (77)
|
||||
ebx - SSF_WAKE (3)
|
||||
======================================================================
|
||||
Remarks:
|
||||
* Subfunctions 4-7 are reserved and currently return -1.
|
||||
@@ -5401,8 +5343,8 @@ Remarks:
|
||||
* Only pipe descriptors are supported.
|
||||
|
||||
---------------------- Constants for registers: ----------------------
|
||||
eax - SF_POSIX (77)
|
||||
ebx - SSF_FD_READ (10)
|
||||
eax - SF_FUTEX (77)
|
||||
ebx - SSF_FILE_READ (10)
|
||||
======================================================================
|
||||
=========== Function 77, Subfunction 11, Write to file. =============
|
||||
======================================================================
|
||||
@@ -5420,8 +5362,8 @@ Remarks:
|
||||
* Only pipe descriptors are supported.
|
||||
|
||||
---------------------- Constants for registers: ----------------------
|
||||
eax - SF_POSIX (77)
|
||||
ebx - SSF_FD_WRITE (11)
|
||||
eax - SF_FUTEX (77)
|
||||
ebx - SSF_FILE_WRITE (11)
|
||||
======================================================================
|
||||
========== Function 77, Subfunction 13, Create pipe. ================
|
||||
======================================================================
|
||||
@@ -5439,8 +5381,8 @@ Remarks:
|
||||
write handle.
|
||||
|
||||
---------------------- Constants for registers: ----------------------
|
||||
eax - SF_POSIX (77)
|
||||
ebx - SSF_FD_PIPE2 (13)
|
||||
eax - SF_FUTEX (77)
|
||||
ebx - SSF_PIPE_CREATE (13)
|
||||
======================================================================
|
||||
=== Function 80 - file system interface with parameter of encoding ===
|
||||
======================================================================
|
||||
|
||||
+72
-1034
File diff suppressed because it is too large.
Load diff
@@ -2405,12 +2405,11 @@ fat_Write:
|
||||
; hd_extend_file can return three error codes: FAT table error, device error or disk full.
|
||||
; First two cases are fatal errors, in third case we may write some data
|
||||
cmp al, ERROR_DISK_FULL
|
||||
jnz .noWrite
|
||||
jnz @f
|
||||
; correct number of bytes to write
|
||||
mov ecx, [edi+28]
|
||||
cmp ecx, ebx
|
||||
ja .length_ok
|
||||
.noWrite:
|
||||
push 0
|
||||
.ret:
|
||||
pop eax eax eax ecx ecx
|
||||
|
||||
@@ -182,20 +182,8 @@ proc file_system_is_operation_safe stdcall, inf_struct_ptr: dword
|
||||
|
||||
.case6:
|
||||
cmp dword [ebx], 6
|
||||
jnz .case11
|
||||
mov ecx, 32
|
||||
jmp .end_switch
|
||||
|
||||
.case11:
|
||||
cmp dword [ebx], 11
|
||||
jnz .case12
|
||||
stdcall is_string_userspace, edx
|
||||
jmp .ret
|
||||
|
||||
.case12:
|
||||
cmp dword [ebx], 12
|
||||
jnz .switch_none
|
||||
mov ecx, dword [ebx + 12]
|
||||
mov ecx, 32
|
||||
jmp .end_switch
|
||||
|
||||
.switch_none:
|
||||
|
||||
@@ -253,10 +253,9 @@ UTF16to8_string:
|
||||
|
||||
UTF16to8:
|
||||
; in:
|
||||
; ax = UTF-16 char
|
||||
; eax = UTF-16 char
|
||||
; edi -> buffer for UTF-8 char (increasing)
|
||||
; ecx = byte counter (decreasing)
|
||||
movzx eax, ax
|
||||
dec ecx
|
||||
js .ret
|
||||
cmp eax, 80h
|
||||
|
||||
@@ -48,10 +48,6 @@ dtext:
|
||||
add esp, 28
|
||||
ret
|
||||
|
||||
.nomem:
|
||||
add esp, 40
|
||||
ret
|
||||
|
||||
.redirect:
|
||||
mov ebp, [edi]
|
||||
add edi, 8
|
||||
@@ -85,8 +81,6 @@ dtext:
|
||||
mov [esp+32], eax
|
||||
imul ebp, eax
|
||||
stdcall kernel_alloc, ebp
|
||||
test eax, eax
|
||||
jz .nomem
|
||||
mov ecx, ebp
|
||||
shr ecx, 2
|
||||
mov [esp+36], eax
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; ;;
|
||||
;; Copyright (C) KolibriOS team 2004-2026. All rights reserved. ;;
|
||||
;; Copyright (C) KolibriOS team 2004-2024. All rights reserved. ;;
|
||||
;; Distributed under terms of the GNU General Public License ;;
|
||||
;; ;;
|
||||
;; IPv4.INC ;;
|
||||
@@ -765,9 +765,9 @@ ipv4_output_raw:
|
||||
push ebx ; push the mac
|
||||
push ax
|
||||
|
||||
inc [IPv4_packets_tx + edi]
|
||||
inc [IPv4_packets_tx + 4*edi]
|
||||
mov ax, ETHER_PROTO_IPv4
|
||||
mov ebx, [net_device_list + edi]
|
||||
mov ebx, [net_device_list + 4*edi]
|
||||
mov ecx, [esp + 6 + 4]
|
||||
add ecx, sizeof.IPv4_header
|
||||
mov edx, esp
|
||||
@@ -951,7 +951,7 @@ endp
|
||||
; edi = device number*4 ;
|
||||
; ;
|
||||
; DESTROYED: ;
|
||||
; ebx, ecx ;
|
||||
; ecx ;
|
||||
; ;
|
||||
;-----------------------------------------------------------------;
|
||||
align 4
|
||||
@@ -964,7 +964,6 @@ ipv4_route:
|
||||
cmp eax, 0xffffffff
|
||||
je .broadcast
|
||||
|
||||
; Check for on-link
|
||||
xor edi, edi
|
||||
.loop:
|
||||
mov ebx, [IPv4_address + edi]
|
||||
@@ -979,55 +978,9 @@ ipv4_route:
|
||||
cmp edi, 4*NET_DEVICES_MAX
|
||||
jb .loop
|
||||
|
||||
; no on-link match, find first device with a gateway
|
||||
mov edi, 4 ; skip loopback device
|
||||
.loop_gw:
|
||||
cmp [IPv4_gateway + edi], 0
|
||||
jne .found_gw
|
||||
add edi, 4
|
||||
cmp edi, 4*NET_DEVICES_MAX
|
||||
jb .loop_gw
|
||||
jmp .loopback ; no gateway found, fall-back to loopback device
|
||||
|
||||
.found_gw:
|
||||
mov eax, [IPv4_gateway + edi]
|
||||
jmp .got_it
|
||||
|
||||
mov eax, [IPv4_gateway + 4] ; TODO: let user (or a user space daemon) configure default route
|
||||
.broadcast:
|
||||
; broadcast: we will do our best without full routing..
|
||||
|
||||
; find the first non loopback device which has an active link without IP address
|
||||
mov edi, 4 ; skip loopback device
|
||||
.bc_loop1:
|
||||
mov ebx, [net_device_list + edi]
|
||||
test ebx, ebx
|
||||
jz @f
|
||||
cmp [ebx + NET_DEVICE.link_state], 0
|
||||
je @f
|
||||
cmp [IPv4_address + edi], 0
|
||||
je .got_it
|
||||
@@:
|
||||
add edi, 4
|
||||
cmp edi, 4*NET_DEVICES_MAX
|
||||
jb .bc_loop1
|
||||
|
||||
; If there is no such device, try the one with active link and IP address
|
||||
mov edi, 4 ; skip loopback device
|
||||
.bc_loop2:
|
||||
mov ebx, [net_device_list + edi]
|
||||
test ebx, ebx
|
||||
jz @f
|
||||
cmp [ebx + NET_DEVICE.link_state], 0
|
||||
jne .got_it
|
||||
@@:
|
||||
add edi, 4
|
||||
cmp edi, 4*NET_DEVICES_MAX
|
||||
jb .bc_loop2
|
||||
; jmp .loopback ; no gateway found, fall-back to loopback device
|
||||
|
||||
.loopback:
|
||||
xor edi, edi ; nowhere to go for now.. route it to the loopback device
|
||||
|
||||
mov edi, 4 ; TODO: same as above
|
||||
.got_it:
|
||||
DEBUGF DEBUG_NETWORK_VERBOSE, "IPv4_route: %u\n", edi
|
||||
test edx, edx
|
||||
|
||||
@@ -279,8 +279,10 @@ sys_socket:
|
||||
dd socket_get_opt ; 9
|
||||
dd socket_pair ; 10
|
||||
|
||||
;dd socket_sendto ; 11
|
||||
;dd socket_recvfrom ; 12
|
||||
dd socket_getpeername ; 11
|
||||
dd socket_getsockname ; 12
|
||||
;dd socket_sendto ; 13
|
||||
;dd socket_recvfrom ; 14
|
||||
.number = ($ - .table) / 4 - 1
|
||||
|
||||
.error:
|
||||
@@ -780,6 +782,8 @@ socket_close:
|
||||
|
||||
cmp [eax + SOCKET.Protocol], IP_PROTO_TCP
|
||||
jne .free
|
||||
test [eax + SOCKET.state], SS_ISCONNECTED
|
||||
jz @f
|
||||
test [eax + SOCKET.state], SS_ISDISCONNECTING
|
||||
jnz @f
|
||||
call tcp_disconnect
|
||||
@@ -1394,6 +1398,139 @@ socket_pair:
|
||||
|
||||
|
||||
|
||||
;-----------------------------------------------------------------;
|
||||
; ;
|
||||
; socket_getpeername: Get name of connected peer socket. ;
|
||||
; ;
|
||||
; IN: ecx = socket number ;
|
||||
; edx = pointer to sockaddr struct ;
|
||||
; esi = length of sockaddr struct ;
|
||||
; ;
|
||||
; OUT: eax = length of sockaddr struct ;
|
||||
; eax = -1 on error ;
|
||||
; ebx = errorcode on error ;
|
||||
; ;
|
||||
;-----------------------------------------------------------------;
|
||||
align 4
|
||||
socket_getpeername:
|
||||
|
||||
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_getpeername: socknum=%u sockaddr=%x length=%u\n", ecx, edx, esi
|
||||
|
||||
call socket_num_to_ptr
|
||||
test eax, eax
|
||||
jz .notsock
|
||||
|
||||
stdcall is_region_userspace, edx, esi
|
||||
jnz .efault
|
||||
|
||||
cmp [eax + SOCKET.Domain], AF_INET4
|
||||
jne .invalid
|
||||
|
||||
cmp esi, 8 ; domain + port + ipv4_addr
|
||||
jb .errlen
|
||||
|
||||
mov word[edx], AF_INET4
|
||||
mov esi, edx
|
||||
|
||||
xor edx, edx
|
||||
cmp [eax + SOCKET.Type], SOCK_RAW
|
||||
je .raw_protocol
|
||||
|
||||
mov dx, [eax + TCP_SOCKET.RemotePort]
|
||||
.raw_protocol:
|
||||
cmp [eax + SOCKET.state], SS_ISCONNECTED
|
||||
jne .notconn
|
||||
|
||||
mov [esi + sockaddr.port], dx
|
||||
|
||||
mov edx, [eax + IP_SOCKET.RemoteIP]
|
||||
mov [esi + sockaddr.ip], edx
|
||||
|
||||
mov dword[esp + SYSCALL_STACK.eax], 8
|
||||
ret
|
||||
|
||||
.efault:
|
||||
mov dword[esp + SYSCALL_STACK.eax], -1
|
||||
mov dword[esp + SYSCALL_STACK.ebx], EFAULT
|
||||
ret
|
||||
|
||||
.notconn:
|
||||
mov dword[esp + SYSCALL_STACK.ebx], ENOTCONN
|
||||
mov dword[esp + SYSCALL_STACK.eax], -1
|
||||
ret
|
||||
.no_inet4:
|
||||
.errlen:
|
||||
.invalid:
|
||||
mov dword[esp + SYSCALL_STACK.ebx], EINVAL
|
||||
mov dword[esp + SYSCALL_STACK.eax], -1
|
||||
ret
|
||||
.notsock:
|
||||
mov dword[esp + SYSCALL_STACK.ebx], ENOTSOCK
|
||||
mov dword[esp + SYSCALL_STACK.eax], -1
|
||||
ret
|
||||
;-----------------------------------------------------------------;
|
||||
; ;
|
||||
; socket_getsockname: Get socket name. ;
|
||||
; ;
|
||||
; IN: ecx = socket number ;
|
||||
; edx = pointer to sockaddr struct ;
|
||||
; esi = length of sockaddr struct ;
|
||||
; ;
|
||||
; OUT: eax = length of sockaddr struct ;
|
||||
; eax = -1 on error ;
|
||||
; ebx = errorcode on error ;
|
||||
; ;
|
||||
;-----------------------------------------------------------------;
|
||||
align 4
|
||||
socket_getsockname:
|
||||
|
||||
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_getsockname: socknum=%u sockaddr=%x length=%u\n", ecx, edx, esi
|
||||
|
||||
call socket_num_to_ptr
|
||||
test eax, eax
|
||||
jz .notsock
|
||||
|
||||
stdcall is_region_userspace, edx, esi
|
||||
jnz .efault
|
||||
|
||||
cmp [eax + SOCKET.Domain], AF_INET4
|
||||
jne .invalid
|
||||
|
||||
cmp esi, 8 ; domain + port + ipv4_addr
|
||||
jb .errlen
|
||||
|
||||
mov word[edx], AF_INET4
|
||||
mov esi, edx
|
||||
|
||||
xor edx, edx
|
||||
cmp [eax + SOCKET.Type], SOCK_RAW
|
||||
je .raw_protocol
|
||||
|
||||
mov dx, [eax + TCP_SOCKET.RemotePort]
|
||||
.raw_protocol:
|
||||
mov [esi + sockaddr.port], dx
|
||||
|
||||
mov edx, [eax + IP_SOCKET.RemoteIP]
|
||||
mov [esi + sockaddr.ip], edx
|
||||
|
||||
mov dword[esp + SYSCALL_STACK.eax], 8
|
||||
ret
|
||||
|
||||
.efault:
|
||||
mov dword[esp + SYSCALL_STACK.eax], -1
|
||||
mov dword[esp + SYSCALL_STACK.ebx], EFAULT
|
||||
ret
|
||||
|
||||
.errlen:
|
||||
.invalid:
|
||||
mov dword[esp + SYSCALL_STACK.ebx], EINVAL
|
||||
mov dword[esp + SYSCALL_STACK.eax], -1
|
||||
ret
|
||||
.notsock:
|
||||
mov dword[esp + SYSCALL_STACK.ebx], ENOTSOCK
|
||||
mov dword[esp + SYSCALL_STACK.eax], -1
|
||||
ret
|
||||
|
||||
;-----------------------------------------------------------------;
|
||||
; ;
|
||||
; socket_debug: Copy socket variables to application buffer. ;
|
||||
@@ -2124,11 +2261,11 @@ socket_free:
|
||||
mov ebx, eax
|
||||
cmp [eax + STREAM_SOCKET.rcv.start_ptr], 0
|
||||
je @f
|
||||
stdcall kernel_free, [eax + STREAM_SOCKET.rcv.start_ptr]
|
||||
stdcall free_kernel_space, [eax + STREAM_SOCKET.rcv.start_ptr]
|
||||
@@:
|
||||
cmp [ebx + STREAM_SOCKET.snd.start_ptr], 0
|
||||
je @f
|
||||
stdcall kernel_free, [ebx + STREAM_SOCKET.snd.start_ptr]
|
||||
stdcall free_kernel_space, [ebx + STREAM_SOCKET.snd.start_ptr]
|
||||
@@:
|
||||
mov eax, ebx
|
||||
.no_stream:
|
||||
|
||||
@@ -118,7 +118,7 @@ SS_MORETOCOME = 0x4000
|
||||
SS_BLOCKED = 0x8000
|
||||
|
||||
|
||||
SOCKET_BUFFER_SIZE = 4096*32 ; must be 4096*(power of 2) where 'power of 2' is at least 8
|
||||
SOCKET_BUFFER_SIZE = 4096*8 ; must be 4096*(power of 2) where 'power of 2' is at least 8
|
||||
MAX_backlog = 20 ; maximum backlog for stream sockets
|
||||
|
||||
; Error Codes
|
||||
@@ -139,6 +139,9 @@ EISCONN = 56
|
||||
ETIMEDOUT = 60
|
||||
ECONNREFUSED = 61
|
||||
|
||||
EFAULT = 14 ; copy, defined in posix/posix.inc ; Bad address
|
||||
ENOTSOCK = 38 ; FreeBSD error code, Socket operation on non-socket
|
||||
|
||||
; Api protocol numbers
|
||||
API_ETH = 0
|
||||
API_IPv4 = 1
|
||||
|
||||
@@ -320,12 +320,12 @@ tcp_respond:
|
||||
stosb
|
||||
mov eax, SOCKET_BUFFER_SIZE
|
||||
sub eax, [esi + STREAM_SOCKET.rcv.size]
|
||||
mov cl, [esi + TCP_SOCKET.RCV_SCALE]
|
||||
shr eax, cl ; scale first, then clamp to the
|
||||
cmp eax, TCP_max_win ; 16-bit field maximum
|
||||
cmp eax, TCP_max_win
|
||||
jbe .lessthanmax
|
||||
mov eax, TCP_max_win
|
||||
.lessthanmax:
|
||||
mov cl, [esi + TCP_SOCKET.RCV_SCALE]
|
||||
shr eax, cl
|
||||
|
||||
xchg al, ah
|
||||
stosw ; window
|
||||
@@ -488,7 +488,7 @@ tcp_set_persist:
|
||||
; Start/restart persistence timer.
|
||||
|
||||
tcpt_rangeset [eax + TCP_SOCKET.timer_persist], ebx, TCP_time_pers_min, TCP_time_pers_max
|
||||
or [eax + TCP_SOCKET.timer_flags], timer_flag_persist
|
||||
or [ebx + TCP_SOCKET.timer_flags], timer_flag_persist
|
||||
pop ebx
|
||||
|
||||
cmp [eax + TCP_SOCKET.t_rxtshift], TCP_max_rxtshift
|
||||
|
||||
@@ -111,13 +111,13 @@ proc tcp_timer_640ms
|
||||
|
||||
DEBUGF DEBUG_NETWORK_VERBOSE, "socket %x: Keepalive expired\n", eax
|
||||
|
||||
cmp [eax + TCP_SOCKET.t_state], TCPS_ESTABLISHED
|
||||
jae .dont_kill
|
||||
cmp [eax + TCP_SOCKET.state], TCPS_ESTABLISHED
|
||||
ja .dont_kill
|
||||
|
||||
push [eax + SOCKET.NextPtr]
|
||||
push eax
|
||||
call tcp_disconnect
|
||||
pop eax
|
||||
jmp .check_only
|
||||
jmp .loop
|
||||
|
||||
.dont_kill:
|
||||
test [eax + SOCKET.options], SO_KEEPALIVE
|
||||
|
||||
@@ -125,7 +125,7 @@ SF_STYLE_SETTINGS=48
|
||||
SSF_SET_FONT_SIZE=12
|
||||
SF_APM=49
|
||||
SF_SET_WINDOW_SHAPE=50
|
||||
SF_THREAD_CONTROL=51
|
||||
SF_CREATE_THREAD=51
|
||||
SSF_CREATE_THREAD=1
|
||||
SSF_GET_CURR_THREAD_SLOT=2
|
||||
SSF_GET_THREAD_PRIORITY=3
|
||||
@@ -281,14 +281,14 @@ SF_NETWORK_PROTOCOL=76
|
||||
SSF_ARP_DEL_ENTRY=50005h
|
||||
SSF_ARP_SEND_ANNOUNCE=50006h
|
||||
SSF_ARP_CONFLICTS_COUNT=50007h
|
||||
SF_POSIX=77
|
||||
SSF_FUTEX_CREATE=0
|
||||
SSF_FUTEX_DESTROY=1
|
||||
SSF_FUTEX_WAIT=2
|
||||
SSF_FUTEX_WAKE=3
|
||||
SSF_FD_READ=10
|
||||
SSF_FD_WRITE=11
|
||||
SSF_FD_PIPE2=13
|
||||
SF_FUTEX=77
|
||||
SSF_CREATE=0
|
||||
SSF_DESTROY=1
|
||||
SSF_WAIT=2
|
||||
SSF_WAKE=3
|
||||
SSF_FILE_READ=10
|
||||
SSF_FILE_WRITE=11
|
||||
SSF_PIPE_CREATE=13
|
||||
|
||||
; File system errors:
|
||||
FSERR_SUCCESS=0
|
||||
|
||||
@@ -1111,7 +1111,7 @@ end if
|
||||
mov dword [edx+8],ebx
|
||||
mov dword [edx+4],ecx
|
||||
mov dword [edx],Kolibri_ThreadFinish
|
||||
mov eax,SF_THREAD_CONTROL
|
||||
mov eax,SF_CREATE_THREAD
|
||||
mov ebx,1
|
||||
mov ecx,@Kolibri@ThreadMain$qpvt1
|
||||
int 0x40
|
||||
|
||||
@@ -1,2 +0,0 @@
|
||||
@fasm free3d04.asm free3d04
|
||||
if not exist free3d04 ( @pause )
|
||||
@@ -0,0 +1,5 @@
|
||||
@erase lang.inc
|
||||
@echo lang fix en_US >lang.inc
|
||||
@fasm free3d04.asm free3d04
|
||||
@erase lang.inc
|
||||
@pause
|
||||
@@ -0,0 +1,5 @@
|
||||
@erase lang.inc
|
||||
@echo lang fix ru_RU >lang.inc
|
||||
@fasm free3d04.asm free3d04
|
||||
@erase lang.inc
|
||||
@pause
|
||||
@@ -9,10 +9,9 @@
|
||||
;
|
||||
; Compile with FASM for Menuet (requires .INC files - see DATA Section)
|
||||
;
|
||||
; Willow - greatly srinked code size by using packed texture and FPU to calculate sine table
|
||||
; Willow - greatly srinked code size by using GIF texture and FPU to calculate sine table
|
||||
;
|
||||
; Textures are stored as a single 64x512 PNG embedded into the binary and
|
||||
; decoded at startup with libimg.
|
||||
; !!!! Don't use GIF_LITE.INC in your apps - it's modified for FREE3D !!!!
|
||||
;
|
||||
; Heavyiron - new 0-function of drawing window from kolibri (do not work correctly with menuet)
|
||||
|
||||
@@ -39,17 +38,15 @@ use32
|
||||
dd APP_MEM;0x100000 ; memory for app
|
||||
dd APP_MEM;0x100000 ; esp
|
||||
dd 0x0 , 0x0 ; I_Param , I_Icon
|
||||
include 'lang.inc'
|
||||
include '..\..\macros.inc'
|
||||
include '..\..\proc32.inc'
|
||||
include '..\..\dll.inc'
|
||||
include '..\..\develop\libraries\libs-dev\libimg\libimg.inc'
|
||||
COLOR_ORDER equ OTHER
|
||||
include 'gif_lite.inc'
|
||||
|
||||
START: ; start of execution
|
||||
mcall 68,11 ; init heap, libimg needs it
|
||||
stdcall dll.Load,@IMPORT
|
||||
test eax,eax
|
||||
jnz finish
|
||||
call load_textures
|
||||
mov esi,textures
|
||||
mov edi,ceil-8
|
||||
call ReadGIF
|
||||
mov esi,sinus
|
||||
mov ecx,360*10
|
||||
fninit
|
||||
@@ -294,34 +291,6 @@ m_right: ; turn right
|
||||
mcall
|
||||
|
||||
|
||||
; *********************************************
|
||||
; ******* LOAD TEXTURES ********
|
||||
; *********************************************
|
||||
; Decodes the embedded 64x512 PNG (8 stacked 64x64 tiles) into the raw
|
||||
; 0x00RRGGBB texture bank at [ceil].
|
||||
|
||||
load_textures:
|
||||
invoke img.decode,textures,textures.size,0
|
||||
test eax,eax
|
||||
jz finish
|
||||
mov ebx,eax
|
||||
invoke img.convert,ebx,0,Image.bpp32,0,0
|
||||
push eax
|
||||
invoke img.destroy,ebx
|
||||
pop ebx
|
||||
test ebx,ebx
|
||||
jz finish
|
||||
mov esi,[ebx+Image.Data]
|
||||
mov edi,ceil
|
||||
mov ecx,TEX_SIZE*8/4
|
||||
.copy:
|
||||
lodsd
|
||||
and eax,0x00FFFFFF ; drop alpha, the renderer stores 32 bit dwords
|
||||
stosd ; into a 24 bit image buffer
|
||||
loop .copy
|
||||
invoke img.destroy,ebx
|
||||
ret
|
||||
|
||||
; *********************************************
|
||||
; ******* WINDOW DEFINITIONS AND DRAW ********
|
||||
; *********************************************
|
||||
@@ -1011,21 +980,13 @@ dd 0x0001FFFF ; initial player position * 0xFFFF
|
||||
vpy:
|
||||
dd 0x0001FFFF
|
||||
|
||||
title db 'Fisheye Raycasting Engine Etc. FREE3D',0
|
||||
title db 'FISHEYE RAYCASTING ENGINE ETC. FREE3D',0
|
||||
|
||||
sindegree dd 0.0
|
||||
sininc dd 0.0017453292519943295769236907684886
|
||||
sindiv dd 6553.5
|
||||
textures:
|
||||
file 'texture.png'
|
||||
.size = $ - textures
|
||||
|
||||
align 16
|
||||
@IMPORT:
|
||||
|
||||
library libimg , 'libimg.obj'
|
||||
|
||||
import libimg , libimg.init , 'lib_init' , img.decode , 'img_decode' , img.convert , 'img_convert', img.destroy , 'img_destroy'
|
||||
file 'texture.gif'
|
||||
|
||||
align 4
|
||||
|
||||
|
||||
@@ -0,0 +1,487 @@
|
||||
; GIF LITE v3.0 by Willow
|
||||
; Written in pure assembler by Ivushkin Andrey aka Willow
|
||||
; Modified by Diamond
|
||||
;
|
||||
; This include file will contain functions to handle GIF image format
|
||||
;
|
||||
; Created: August 15, 2004
|
||||
; Last changed: June 24, 2007
|
||||
|
||||
; Requires kglobals.inc (iglobal/uglobal macro)
|
||||
; (program must 'include "kglobals.inc"' and say 'IncludeUGlobal'
|
||||
; somewhere in uninitialized data area).
|
||||
|
||||
; Configuration: [changed from program which includes this file]
|
||||
; 1. The constant COLOR_ORDER: must be one of
|
||||
; PALETTE - for 8-bit image with palette (sysfunction 65)
|
||||
; MENUETOS - for MenuetOS and KolibriOS color order (sysfunction 7)
|
||||
; OTHER - for standard color order
|
||||
; 2. Define constant GIF_SUPPORT_INTERLACED if you want to support interlaced
|
||||
; GIFs.
|
||||
; 3. Single image mode vs multiple image mode:
|
||||
; if the program defines the variable 'gif_img_count' of type dword
|
||||
; somewhere, ReadGIF will enter multiple image mode: gif_img_count
|
||||
; will be initialized with image count, output format is GIF_list,
|
||||
; the function GetGIFinfo retrieves Nth image info. Otherwise, ReadGIF
|
||||
; uses single image mode: exit after end of first image, output is
|
||||
; <dd width,height, times width*height[*3] db image>
|
||||
|
||||
if ~ (COLOR_ORDER in <PALETTE,MENUETOS,OTHER>)
|
||||
; This message may not appear under MenuetOS, so watch...
|
||||
display 'Please define COLOR_ORDER: PALETTE, MENUETOS or OTHER',13,10
|
||||
end if
|
||||
|
||||
if defined gif_img_count
|
||||
; virtual structure, used internally
|
||||
|
||||
struct GIF_list
|
||||
NextImg rd 1
|
||||
Left rw 1
|
||||
Top rw 1
|
||||
Width rw 1
|
||||
Height rw 1
|
||||
Delay rd 1
|
||||
Displacement rd 1 ; 0 = not specified
|
||||
; 1 = do not dispose
|
||||
; 2 = restore to background color
|
||||
; 3 = restore to previous
|
||||
if COLOR_ORDER eq PALETTE
|
||||
Image rd 1
|
||||
end if
|
||||
ends
|
||||
|
||||
struct GIF_info
|
||||
Left rw 1
|
||||
Top rw 1
|
||||
Width rw 1
|
||||
Height rw 1
|
||||
Delay rd 1
|
||||
Displacement rd 1
|
||||
if COLOR_ORDER eq PALETTE
|
||||
Palette rd 1
|
||||
end if
|
||||
ends
|
||||
|
||||
; ****************************************
|
||||
; FUNCTION GetGIFinfo - retrieve Nth image info
|
||||
; ****************************************
|
||||
; in:
|
||||
; esi - pointer to image list header
|
||||
; ecx - image_index (0...img_count-1)
|
||||
; edi - pointer to GIF_info structure to be filled
|
||||
|
||||
; out:
|
||||
; eax - pointer to RAW data, or 0, if error
|
||||
|
||||
GetGIFinfo:
|
||||
push esi ecx edi
|
||||
xor eax,eax
|
||||
jecxz .eloop
|
||||
.lp:
|
||||
mov esi,[esi]
|
||||
test esi,esi
|
||||
jz .error
|
||||
loop .lp
|
||||
.eloop:
|
||||
lodsd
|
||||
movsd
|
||||
movsd
|
||||
movsd
|
||||
movsd
|
||||
if COLOR_ORDER eq PALETTE
|
||||
lodsd
|
||||
mov [edi],esi
|
||||
else
|
||||
mov eax,esi
|
||||
end if
|
||||
.error:
|
||||
pop edi ecx esi
|
||||
ret
|
||||
|
||||
end if
|
||||
|
||||
_null fix 0x1000
|
||||
|
||||
; ****************************************
|
||||
; FUNCTION ReadGIF - unpacks GIF image
|
||||
; ****************************************
|
||||
; in:
|
||||
; esi - pointer to GIF file in memory
|
||||
; edi - pointer to output image list
|
||||
|
||||
; out:
|
||||
; eax - 0, all OK;
|
||||
; eax - 1, invalid signature;
|
||||
; eax >=8, unsupported image attributes
|
||||
;
|
||||
|
||||
ReadGIF:
|
||||
push esi edi
|
||||
mov [.cur_info],edi
|
||||
xor eax,eax
|
||||
mov [.globalColor],eax
|
||||
if defined gif_img_count
|
||||
mov [gif_img_count],eax
|
||||
mov [.anim_delay],eax
|
||||
mov [.anim_disp],eax
|
||||
end if
|
||||
inc eax
|
||||
cmp dword[esi],'GIF8'
|
||||
jne .ex ; signature
|
||||
mov ecx,[esi+0xa]
|
||||
add esi,0xd
|
||||
mov edi,esi
|
||||
test cl,cl
|
||||
jns .nextblock
|
||||
mov [.globalColor],esi
|
||||
call .Gif_skipmap
|
||||
.nextblock:
|
||||
cmp byte[edi],0x21
|
||||
jne .noextblock
|
||||
inc edi
|
||||
if defined gif_img_count
|
||||
cmp byte[edi],0xf9 ; Graphic Control Ext
|
||||
jne .no_gc
|
||||
movzx eax,word [edi+3]
|
||||
mov [.anim_delay],eax
|
||||
mov al,[edi+2]
|
||||
shr al,2
|
||||
and eax,7
|
||||
mov [.anim_disp],eax
|
||||
add edi,7
|
||||
jmp .nextblock
|
||||
.no_gc:
|
||||
end if
|
||||
inc edi
|
||||
.block_skip:
|
||||
movzx eax,byte[edi]
|
||||
lea edi,[edi+eax+1]
|
||||
test eax,eax
|
||||
jnz .block_skip
|
||||
jmp .nextblock
|
||||
.noextblock:
|
||||
mov al,8
|
||||
cmp byte[edi],0x2c ; image beginning
|
||||
jne .ex
|
||||
if defined gif_img_count
|
||||
inc [gif_img_count]
|
||||
end if
|
||||
inc edi
|
||||
mov esi,[.cur_info]
|
||||
if defined gif_img_count
|
||||
add esi,4
|
||||
end if
|
||||
xchg esi,edi
|
||||
if defined GIF_SUPPORT_INTERLACED
|
||||
movzx ecx,word[esi+4]
|
||||
mov [.width],ecx
|
||||
movzx eax,word[esi+6]
|
||||
imul eax,ecx
|
||||
if ~(COLOR_ORDER eq PALETTE)
|
||||
lea eax,[eax*3]
|
||||
end if
|
||||
mov [.img_end],eax
|
||||
inc eax
|
||||
mov [.row_end],eax
|
||||
and [.pass],0
|
||||
test byte[esi+8],40h
|
||||
jz @f
|
||||
if ~(COLOR_ORDER eq PALETTE)
|
||||
lea ecx,[ecx*3]
|
||||
end if
|
||||
mov [.row_end],ecx
|
||||
@@:
|
||||
end if
|
||||
if defined gif_img_count
|
||||
movsd
|
||||
movsd
|
||||
mov eax,[.anim_delay]
|
||||
stosd
|
||||
mov eax,[.anim_disp]
|
||||
stosd
|
||||
else
|
||||
movzx eax,word[esi+4]
|
||||
stosd
|
||||
movzx eax,word[esi+6]
|
||||
stosd
|
||||
add esi,8
|
||||
end if
|
||||
push edi
|
||||
mov ecx,[esi]
|
||||
inc esi
|
||||
test cl,cl
|
||||
js .uselocal
|
||||
push [.globalColor]
|
||||
mov edi,esi
|
||||
jmp .setPal
|
||||
.uselocal:
|
||||
call .Gif_skipmap
|
||||
push esi
|
||||
.setPal:
|
||||
movzx ecx,byte[edi]
|
||||
inc ecx
|
||||
mov [.codesize],ecx
|
||||
dec ecx
|
||||
if ~(COLOR_ORDER eq PALETTE)
|
||||
pop [.Palette]
|
||||
end if
|
||||
lea esi,[edi+1]
|
||||
mov edi,.gif_workarea
|
||||
xor eax,eax
|
||||
lodsb ; eax - block_count
|
||||
add eax,esi
|
||||
mov [.block_ofs],eax
|
||||
mov [.bit_count],8
|
||||
mov eax,1
|
||||
shl eax,cl
|
||||
mov [.CC],eax
|
||||
mov ecx,eax
|
||||
inc eax
|
||||
mov [.EOI],eax
|
||||
mov eax, _null shl 16
|
||||
.filltable:
|
||||
stosd
|
||||
inc eax
|
||||
loop .filltable
|
||||
if COLOR_ORDER eq PALETTE
|
||||
pop eax
|
||||
pop edi
|
||||
push edi
|
||||
scasd
|
||||
push esi
|
||||
mov esi,eax
|
||||
mov ecx,[.CC]
|
||||
@@:
|
||||
lodsd
|
||||
dec esi
|
||||
bswap eax
|
||||
shr eax,8
|
||||
stosd
|
||||
loop @b
|
||||
pop esi
|
||||
pop eax
|
||||
mov [eax],edi
|
||||
else
|
||||
pop edi
|
||||
end if
|
||||
if defined GIF_SUPPORT_INTERLACED
|
||||
mov [.img_start],edi
|
||||
add [.img_end],edi
|
||||
add [.row_end],edi
|
||||
end if
|
||||
.reinit:
|
||||
mov edx,[.EOI]
|
||||
inc edx
|
||||
push [.codesize]
|
||||
pop [.compsize]
|
||||
call .Gif_get_sym
|
||||
cmp eax,[.CC]
|
||||
je .reinit
|
||||
call .Gif_output
|
||||
.cycle:
|
||||
movzx ebx,ax
|
||||
call .Gif_get_sym
|
||||
cmp eax,edx
|
||||
jae .notintable
|
||||
cmp eax,[.CC]
|
||||
je .reinit
|
||||
cmp eax,[.EOI]
|
||||
je .end
|
||||
call .Gif_output
|
||||
.add:
|
||||
mov dword [.gif_workarea+edx*4],ebx
|
||||
cmp edx,0xFFF
|
||||
jae .cycle
|
||||
inc edx
|
||||
bsr ebx,edx
|
||||
cmp ebx,[.compsize]
|
||||
jne .noinc
|
||||
inc [.compsize]
|
||||
.noinc:
|
||||
jmp .cycle
|
||||
.notintable:
|
||||
push eax
|
||||
mov eax,ebx
|
||||
call .Gif_output
|
||||
push ebx
|
||||
movzx eax,bx
|
||||
call .Gif_output
|
||||
pop ebx eax
|
||||
jmp .add
|
||||
.end:
|
||||
if defined GIF_SUPPORT_INTERLACED
|
||||
mov edi,[.img_end]
|
||||
end if
|
||||
if defined gif_img_count
|
||||
mov eax,[.cur_info]
|
||||
mov [eax],edi
|
||||
mov [.cur_info],edi
|
||||
add esi,2
|
||||
xchg esi,edi
|
||||
.nxt:
|
||||
cmp byte[edi],0
|
||||
jnz .continue
|
||||
inc edi
|
||||
jmp .nxt
|
||||
.continue:
|
||||
cmp byte[edi],0x3b
|
||||
jne .nextblock
|
||||
xchg esi,edi
|
||||
and dword [eax],0
|
||||
end if
|
||||
xor eax,eax
|
||||
.ex:
|
||||
pop edi esi
|
||||
ret
|
||||
|
||||
.Gif_skipmap:
|
||||
; in: ecx - image descriptor, esi - pointer to colormap
|
||||
; out: edi - pointer to area after colormap
|
||||
|
||||
and ecx,111b
|
||||
inc ecx ; color map size
|
||||
mov ebx,1
|
||||
shl ebx,cl
|
||||
lea ebx,[ebx*2+ebx]
|
||||
lea edi,[esi+ebx]
|
||||
ret
|
||||
|
||||
.Gif_get_sym:
|
||||
mov ecx,[.compsize]
|
||||
push ecx
|
||||
xor eax,eax
|
||||
.shift:
|
||||
ror byte[esi],1
|
||||
rcr eax,1
|
||||
dec [.bit_count]
|
||||
jnz .loop1
|
||||
inc esi
|
||||
cmp esi,[.block_ofs]
|
||||
jb .noblock
|
||||
push eax
|
||||
xor eax,eax
|
||||
lodsb
|
||||
test eax,eax
|
||||
jnz .nextbl
|
||||
mov eax,[.EOI]
|
||||
sub esi,2
|
||||
add esp,8
|
||||
jmp .exx
|
||||
.nextbl:
|
||||
add eax,esi
|
||||
mov [.block_ofs],eax
|
||||
pop eax
|
||||
.noblock:
|
||||
mov [.bit_count],8
|
||||
.loop1:
|
||||
loop .shift
|
||||
pop ecx
|
||||
rol eax,cl
|
||||
.exx:
|
||||
xor ecx,ecx
|
||||
ret
|
||||
|
||||
.Gif_output:
|
||||
push esi eax edx
|
||||
mov edx,.gif_workarea
|
||||
.next:
|
||||
push word[edx+eax*4]
|
||||
mov ax,word[edx+eax*4+2]
|
||||
inc ecx
|
||||
cmp ax,_null
|
||||
jnz .next
|
||||
shl ebx,16
|
||||
mov bx,[esp]
|
||||
.loop2:
|
||||
pop ax
|
||||
|
||||
if COLOR_ORDER eq PALETTE
|
||||
stosb
|
||||
else
|
||||
lea esi,[eax+eax*2]
|
||||
add esi,[.Palette]
|
||||
|
||||
if COLOR_ORDER eq MENUETOS
|
||||
mov esi,[esi]
|
||||
bswap esi
|
||||
shr esi,8
|
||||
mov [edi],esi
|
||||
add edi,3
|
||||
else
|
||||
movsb
|
||||
movsb
|
||||
movsb
|
||||
mov byte [edi],0
|
||||
inc edi
|
||||
end if
|
||||
end if
|
||||
|
||||
if defined GIF_SUPPORT_INTERLACED
|
||||
cmp edi,[.row_end]
|
||||
jb .norowend
|
||||
mov eax,[.width]
|
||||
if ~(COLOR_ORDER eq PALETTE)
|
||||
lea eax,[eax*3]
|
||||
end if
|
||||
push eax
|
||||
sub edi,eax
|
||||
add eax,eax
|
||||
cmp [.pass],3
|
||||
jz @f
|
||||
add eax,eax
|
||||
cmp [.pass],2
|
||||
jz @f
|
||||
add eax,eax
|
||||
@@:
|
||||
add edi,eax
|
||||
pop eax
|
||||
cmp edi,[.img_end]
|
||||
jb .nextrow
|
||||
mov edi,[.img_start]
|
||||
inc [.pass]
|
||||
add edi,eax
|
||||
cmp [.pass],3
|
||||
jz @f
|
||||
add edi,eax
|
||||
cmp [.pass],2
|
||||
jz @f
|
||||
add edi,eax
|
||||
add edi,eax
|
||||
@@:
|
||||
.nextrow:
|
||||
add eax,edi
|
||||
mov [.row_end],eax
|
||||
xor eax,eax
|
||||
.norowend:
|
||||
end if
|
||||
|
||||
loop .loop2
|
||||
pop edx eax esi
|
||||
ret
|
||||
|
||||
uglobal
|
||||
align 4
|
||||
ReadGIF.globalColor rd 1
|
||||
ReadGIF.cur_info rd 1 ; image table pointer
|
||||
ReadGIF.codesize rd 1
|
||||
ReadGIF.compsize rd 1
|
||||
ReadGIF.bit_count rd 1
|
||||
ReadGIF.CC rd 1
|
||||
ReadGIF.EOI rd 1
|
||||
if ~(COLOR_ORDER eq PALETTE)
|
||||
ReadGIF.Palette rd 1
|
||||
end if
|
||||
ReadGIF.block_ofs rd 1
|
||||
if defined GIF_SUPPORT_INTERLACED
|
||||
ReadGIF.row_end rd 1
|
||||
ReadGIF.img_end rd 1
|
||||
ReadGIF.img_start rd 1
|
||||
ReadGIF.pass rd 1
|
||||
ReadGIF.width rd 1
|
||||
end if
|
||||
if defined gif_img_count
|
||||
ReadGIF.anim_delay rd 1
|
||||
ReadGIF.anim_disp rd 1
|
||||
end if
|
||||
ReadGIF.gif_workarea rb 16*1024
|
||||
endg
|
||||
@@ -10,11 +10,11 @@ By Dieter Marfurt
|
||||
|
||||
--------------------------------------------
|
||||
|
||||
Format of the texture file:
|
||||
Format of texture include files:
|
||||
|
||||
texture.png - a 64*512 image holding the 8 textures of 64*64 pixels
|
||||
stacked vertically. It is embedded into the binary and decoded at
|
||||
startup with libimg.
|
||||
dd 0x00RRGGBB,0x00RRGGBB....
|
||||
|
||||
for 64*64 pixels.
|
||||
|
||||
Have fun!
|
||||
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 28 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 14 KiB |
@@ -1067,7 +1067,7 @@ end if
|
||||
mov dword [edx+8],ebx
|
||||
mov dword [edx+4],ecx
|
||||
mov dword [edx],Kolibri_ThreadFinish
|
||||
mov eax,SF_THREAD_CONTROL
|
||||
mov eax,SF_CREATE_THREAD
|
||||
mov ebx,1
|
||||
mov ecx,@Kolibri@ThreadMain$qpvt1
|
||||
int 0x40
|
||||
|
||||
@@ -1,29 +0,0 @@
|
||||
Компилятор XD Pascal, [оригинал проекта](https://github.com/vtereshkov/xdpw), автор оригинала Василий Терешков.
|
||||
В [архиве](./release) компилятор и исходники для `xdpw_2026`(версия для Windows) и `xdpk`(версия для KolibriOS).
|
||||
Компилятор также компилирует сам себя из-под KolibriOS.
|
||||
Размер сжатого компилятора менее 30 килобайтов.
|
||||
|
||||
В папке `xdpk/projects` находятся примеры, также там находится сам компилятор под KolibriOS(`xdpk/projects/Compiler`).
|
||||
Чтобы собрать какой-нибудь пример, нужно просто зайти из-под KolibriOS в папку с примером и запустить файл `MAKE.SH`.
|
||||
Скомпилированное приложение должно появиться в той же папке с примером(если нет, то нажмите "обновить"(F5) в файловом менеджере).
|
||||
А для сборки из-под Windows нужно запустить файл `make.bat`.
|
||||
|
||||
Компиляция:
|
||||
* "xdpw_2026/xdpw.exe" — компилирует из-под Windows приложения для Windows
|
||||
* "xdpk/xdpk.exe" — компилирует из-под Windows приложения для KolibriOS
|
||||
* "xdpk/xdpk.kex" — компилирует из-под KolibriOS приложения для KolibriOS
|
||||
|
||||
Компиляторы вырезают недостижимый код (smart linking): бинарники меньше в 1.5–5 раз.
|
||||
Ключ `-nosmart` отключает оптимизацию. В `xdpw_2020` лежит прежний компилятор без неё.
|
||||
|
||||
Для KolibriOS реализованы модули:
|
||||
* CRT
|
||||
* LibImg
|
||||
* LibINI
|
||||
* Network
|
||||
* OpenDlg
|
||||
* ColorDlg
|
||||
* TinyGL
|
||||
|
||||
[Сайт проекта XD Pascal для KolibriOS: xdpk](https://gitflic.ru/project/kolibrios-programming/xd-pascal)
|
||||
[Архивная копия](https://web.archive.org/web/http://forum.cantor.systems/viewtopic.php?id=131) обсуждения на форуме.
|
||||
@@ -1,25 +0,0 @@
|
||||
BSD 2-Clause License
|
||||
|
||||
Copyright (c) 2009-2010, 2019-2020, Vasiliy Tereshkov
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
@@ -1,3 +0,0 @@
|
||||
..\xdpw_2026\xdpw source\XDPK.pas
|
||||
move /y source\xdpk.exe xdpk.exe
|
||||
pause
|
||||
@@ -1,6 +0,0 @@
|
||||
cd source
|
||||
dcc32 xdpk.pas
|
||||
copy xdpk.exe ..\xdpk.exe /y
|
||||
del xdpk.exe, *.dcu
|
||||
cd ..
|
||||
pause
|
||||
@@ -1,24 +0,0 @@
|
||||
program ClrEolTest;
|
||||
|
||||
uses
|
||||
CRT;
|
||||
|
||||
begin
|
||||
|
||||
CRT_initialization;
|
||||
|
||||
WriteLn('Hello, this is a ClrEolTest!');
|
||||
Delay(500);
|
||||
ClrScr;
|
||||
Writeln('The function CLREOL clears all characters from the');
|
||||
Delay(500);
|
||||
Writeln('cursor position to the end of the line within the');
|
||||
Delay(500);
|
||||
Writeln('current text window, without moving the cursor.');
|
||||
Delay(500);
|
||||
Writeln('Press any key to continue . . .');
|
||||
GotoXY(14, 4);
|
||||
ReadKey;
|
||||
ClrEOL;
|
||||
ReadKey;
|
||||
end.
|
||||
@@ -1,23 +0,0 @@
|
||||
{
|
||||
launch this program with some
|
||||
command line arguments
|
||||
if argument has spaces then
|
||||
need to quote them
|
||||
for example:
|
||||
CmdLineArgs.kex param1 param2 "p a r a m 3"
|
||||
note that ParamStr(0) is always present
|
||||
and contents full file path to CmdLineArgs.kex
|
||||
}
|
||||
|
||||
{$APPTYPE CONSOLE}
|
||||
|
||||
program CmdLineArgs;
|
||||
|
||||
var
|
||||
i: LongInt;
|
||||
|
||||
begin
|
||||
WriteLn('ParamCount = ', ParamCount);
|
||||
for i := 0 to ParamCount do
|
||||
WriteLn('ParamStr(', i, ') = ', ParamStr(i));
|
||||
end.
|
||||
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
@@ -1,399 +0,0 @@
|
||||
// XD Pascal - a 32-bit compiler for KolibriOS
|
||||
// Copyright (c) 2009-2010, 2019-2020, Vasiliy Tereshkov
|
||||
|
||||
{$I-}
|
||||
{$H-}
|
||||
|
||||
unit Linker;
|
||||
|
||||
|
||||
interface
|
||||
|
||||
|
||||
uses Common, CodeGen;
|
||||
|
||||
|
||||
procedure InitializeLinker;
|
||||
procedure SetProgramEntryPoint;
|
||||
function AddImportFunc(const ImportLibName, ImportFuncName: TString): LongInt;
|
||||
procedure LinkAndWriteProgram(const ExeName: TString);
|
||||
|
||||
|
||||
|
||||
implementation
|
||||
|
||||
|
||||
const
|
||||
IMGBASE = $0;
|
||||
SECTALIGN = $20;
|
||||
FILEALIGN = SECTALIGN;
|
||||
|
||||
MAXIMPORTLIBS = 100;
|
||||
MAXIMPORTS = 2000;
|
||||
|
||||
|
||||
type
|
||||
TDOSStub = array [0..127] of Byte;
|
||||
|
||||
|
||||
TPEHeader = packed record
|
||||
PE: array [0..3] of TCharacter;
|
||||
Machine: Word;
|
||||
NumberOfSections: Word;
|
||||
TimeDateStamp: LongInt;
|
||||
PointerToSymbolTable: LongInt;
|
||||
NumberOfSymbols: LongInt;
|
||||
SizeOfOptionalHeader: Word;
|
||||
Characteristics: Word;
|
||||
end;
|
||||
|
||||
|
||||
TPEOptionalHeader = packed record
|
||||
Magic: Word;
|
||||
MajorLinkerVersion: Byte;
|
||||
MinorLinkerVersion: Byte;
|
||||
SizeOfCode: LongInt;
|
||||
SizeOfInitializedData: LongInt;
|
||||
SizeOfUninitializedData: LongInt;
|
||||
AddressOfEntryPoint: LongInt;
|
||||
BaseOfCode: LongInt;
|
||||
BaseOfData: LongInt;
|
||||
ImageBase: LongInt;
|
||||
SectionAlignment: LongInt;
|
||||
FileAlignment: LongInt;
|
||||
MajorOperatingSystemVersion: Word;
|
||||
MinorOperatingSystemVersion: Word;
|
||||
MajorImageVersion: Word;
|
||||
MinorImageVersion: Word;
|
||||
MajorSubsystemVersion: Word;
|
||||
MinorSubsystemVersion: Word;
|
||||
Win32VersionValue: LongInt;
|
||||
SizeOfImage: LongInt;
|
||||
SizeOfHeaders: LongInt;
|
||||
CheckSum: LongInt;
|
||||
Subsystem: Word;
|
||||
DllCharacteristics: Word;
|
||||
SizeOfStackReserve: LongInt;
|
||||
SizeOfStackCommit: LongInt;
|
||||
SizeOfHeapReserve: LongInt;
|
||||
SizeOfHeapCommit: LongInt;
|
||||
LoaderFlags: LongInt;
|
||||
NumberOfRvaAndSizes: LongInt;
|
||||
end;
|
||||
|
||||
|
||||
TDataDirectory = packed record
|
||||
VirtualAddress: LongInt;
|
||||
Size: LongInt;
|
||||
end;
|
||||
|
||||
|
||||
TPESectionHeader = packed record
|
||||
Name: array [0..7] of TCharacter;
|
||||
VirtualSize: LongInt;
|
||||
VirtualAddress: LongInt;
|
||||
SizeOfRawData: LongInt;
|
||||
PointerToRawData: LongInt;
|
||||
PointerToRelocations: LongInt;
|
||||
PointerToLinenumbers: LongInt;
|
||||
NumberOfRelocations: Word;
|
||||
NumberOfLinenumbers: Word;
|
||||
Characteristics: LongInt;
|
||||
end;
|
||||
|
||||
|
||||
THeaders = packed record
|
||||
Signature: array [0..7] of TCharacter;
|
||||
Version: LongInt;
|
||||
EntryPoint: LongInt;
|
||||
EndImage: LongInt;
|
||||
Memory: LongInt;
|
||||
StackTop: LongInt;
|
||||
CmdLine: LongInt;
|
||||
FilePath: LongInt;
|
||||
end;
|
||||
|
||||
|
||||
TImportLibName = array [0..15] of TCharacter;
|
||||
TImportFuncName = array [0..31] of TCharacter;
|
||||
|
||||
|
||||
TImportDirectoryTableEntry = packed record
|
||||
Characteristics: LongInt;
|
||||
TimeDateStamp: LongInt;
|
||||
ForwarderChain: LongInt;
|
||||
Name: LongInt;
|
||||
FirstThunk: LongInt;
|
||||
end;
|
||||
|
||||
|
||||
TImportNameTableEntry = packed record
|
||||
Hint: Word;
|
||||
Name: TImportFuncName;
|
||||
end;
|
||||
|
||||
|
||||
TImport = record
|
||||
LibName, FuncName: TString;
|
||||
end;
|
||||
|
||||
|
||||
TImportSectionData = record
|
||||
DirectoryTable: array [1..MAXIMPORTLIBS + 1] of TImportDirectoryTableEntry;
|
||||
LibraryNames: array [1..MAXIMPORTLIBS] of TImportLibName;
|
||||
LookupTable: array [1..MAXIMPORTS + MAXIMPORTLIBS] of LongInt;
|
||||
NameTable: array [1..MAXIMPORTS] of TImportNameTableEntry;
|
||||
NumImports, NumImportLibs: Integer;
|
||||
end;
|
||||
|
||||
|
||||
|
||||
var
|
||||
Headers: THeaders;
|
||||
Import: array [1..MAXIMPORTS] of TImport;
|
||||
ImportSectionData: TImportSectionData;
|
||||
LastImportLibName: TString;
|
||||
ProgramEntryPoint: LongInt;
|
||||
|
||||
CodeSectionHeader_VirtualAddress: LongInt;
|
||||
DataSectionHeader_VirtualAddress: LongInt;
|
||||
BSSSectionHeader_VirtualAddress: LongInt;
|
||||
ImportSectionHeader_VirtualAddress: LongInt;
|
||||
{
|
||||
const
|
||||
DOSStub: TDOSStub =
|
||||
(
|
||||
$4D, $5A, $90, $00, $03, $00, $00, $00, $04, $00, $00, $00, $FF, $FF, $00, $00,
|
||||
$B8, $00, $00, $00, $00, $00, $00, $00, $40, $00, $00, $00, $00, $00, $00, $00,
|
||||
$00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00,
|
||||
$00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $80, $00, $00, $00,
|
||||
$0E, $1F, $BA, $0E, $00, $B4, $09, $CD, $21, $B8, $01, $4C, $CD, $21, $54, $68,
|
||||
$69, $73, $20, $70, $72, $6F, $67, $72, $61, $6D, $20, $63, $61, $6E, $6E, $6F,
|
||||
$74, $20, $62, $65, $20, $72, $75, $6E, $20, $69, $6E, $20, $44, $4F, $53, $20,
|
||||
$6D, $6F, $64, $65, $2E, $0D, $0D, $0A, $24, $00, $00, $00, $00, $00, $00, $00
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
|
||||
procedure Pad(var f: file; Size, Alignment: Integer);
|
||||
var
|
||||
i: Integer;
|
||||
b: Byte;
|
||||
begin
|
||||
b := 0;
|
||||
for i := 0 to Align(Size, Alignment) - Size - 1 do
|
||||
BlockWrite(f, b, 1);
|
||||
end;
|
||||
|
||||
|
||||
|
||||
|
||||
procedure FillHeaders(CodeSize, InitializedDataSize, UninitializedDataSize, ImportSize: Integer);
|
||||
const
|
||||
PATH_SIZE = 1024;
|
||||
PARAMS_SIZE = 256;
|
||||
STACK_SIZE = 1024 * 1024;
|
||||
|
||||
begin
|
||||
FillChar(Headers, SizeOf(Headers), #0);
|
||||
|
||||
CodeSectionHeader_VirtualAddress := Align(SizeOf(Headers), SECTALIGN);
|
||||
DataSectionHeader_VirtualAddress := Align(SizeOf(Headers), SECTALIGN) + Align(CodeSize, SECTALIGN);
|
||||
BSSSectionHeader_VirtualAddress := Align(SizeOf(Headers), SECTALIGN) + Align(CodeSize, SECTALIGN) + Align(InitializedDataSize, SECTALIGN);
|
||||
ImportSectionHeader_VirtualAddress := Align(SizeOf(Headers), SECTALIGN) + Align(CodeSize, SECTALIGN) + Align(InitializedDataSize, SECTALIGN) + Align(UninitializedDataSize, SECTALIGN);
|
||||
|
||||
with Headers do
|
||||
begin
|
||||
Signature[0] := 'M';
|
||||
Signature[1] := 'E';
|
||||
Signature[2] := 'N';
|
||||
Signature[3] := 'U';
|
||||
Signature[4] := 'E';
|
||||
Signature[5] := 'T';
|
||||
Signature[6] := '0';
|
||||
Signature[7] := '1';
|
||||
Version := 1;
|
||||
EntryPoint := Align(SizeOf(Headers), SECTALIGN) + ProgramEntryPoint;
|
||||
EndImage := Align(SizeOf(Headers), SECTALIGN) + Align(CodeSize, SECTALIGN) + Align(InitializedDataSize, SECTALIGN);
|
||||
FilePath := EndImage + Align(UninitializedDataSize, SECTALIGN);
|
||||
Memory := FilePath + PATH_SIZE + PARAMS_SIZE + STACK_SIZE;
|
||||
StackTop := FilePath + PATH_SIZE + PARAMS_SIZE + STACK_SIZE;
|
||||
CmdLine := FilePath + PATH_SIZE;
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
|
||||
|
||||
procedure InitializeLinker;
|
||||
begin
|
||||
FillChar(Import, SizeOf(Import), #0);
|
||||
FillChar(ImportSectionData, SizeOf(ImportSectionData), #0);
|
||||
LastImportLibName := '';
|
||||
ProgramEntryPoint := 0;
|
||||
end;
|
||||
|
||||
|
||||
|
||||
|
||||
procedure SetProgramEntryPoint;
|
||||
begin
|
||||
if ProgramEntryPoint <> 0 then
|
||||
Error('Duplicate program entry point');
|
||||
|
||||
ProgramEntryPoint := GetCodeSize;
|
||||
end;
|
||||
|
||||
|
||||
|
||||
|
||||
function AddImportFunc(const ImportLibName, ImportFuncName: TString): LongInt;
|
||||
begin
|
||||
with ImportSectionData do
|
||||
begin
|
||||
Inc(NumImports);
|
||||
if NumImports > MAXIMPORTS then
|
||||
Error('Maximum number of import functions exceeded');
|
||||
|
||||
Import[NumImports].LibName := ImportLibName;
|
||||
Import[NumImports].FuncName := ImportFuncName;
|
||||
|
||||
if ImportLibName <> LastImportLibName then
|
||||
begin
|
||||
Inc(NumImportLibs);
|
||||
if NumImportLibs > MAXIMPORTLIBS then
|
||||
Error('Maximum number of import libraries exceeded');
|
||||
LastImportLibName := ImportLibName;
|
||||
end;
|
||||
|
||||
Result := (NumImports - 1 + NumImportLibs - 1) * SizeOf(LongInt); // Relocatable
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
|
||||
|
||||
procedure FillImportSection(var ImportSize, LookupTableOffset: Integer);
|
||||
var
|
||||
ImportIndex, ImportLibIndex, LookupIndex: Integer;
|
||||
LibraryNamesOffset, NameTableOffset: Integer;
|
||||
|
||||
begin
|
||||
with ImportSectionData do
|
||||
begin
|
||||
LibraryNamesOffset := SizeOf(DirectoryTable[1]) * (NumImportLibs + 1);
|
||||
LookupTableOffset := LibraryNamesOffset + SizeOf(LibraryNames[1]) * NumImportLibs;
|
||||
NameTableOffset := LookupTableOffset + SizeOf(LookupTable[1]) * (NumImports + NumImportLibs);
|
||||
ImportSize := NameTableOffset + SizeOf(NameTable[1]) * NumImports;
|
||||
|
||||
LastImportLibName := '';
|
||||
ImportLibIndex := 0;
|
||||
LookupIndex := 0;
|
||||
|
||||
for ImportIndex := 1 to NumImports do
|
||||
begin
|
||||
// Add new import library
|
||||
if (ImportLibIndex = 0) or (Import[ImportIndex].LibName <> LastImportLibName) then
|
||||
begin
|
||||
if ImportLibIndex <> 0 then Inc(LookupIndex); // Add null entry before the first thunk of a new library
|
||||
|
||||
Inc(ImportLibIndex);
|
||||
|
||||
DirectoryTable[ImportLibIndex].Name := LibraryNamesOffset + SizeOf(LibraryNames[1]) * (ImportLibIndex - 1);
|
||||
DirectoryTable[ImportLibIndex].FirstThunk := LookupTableOffset + SizeOf(LookupTable[1]) * LookupIndex;
|
||||
|
||||
Move(Import[ImportIndex].LibName[1], LibraryNames[ImportLibIndex], Length(Import[ImportIndex].LibName));
|
||||
|
||||
LastImportLibName := Import[ImportIndex].LibName;
|
||||
end; // if
|
||||
|
||||
// Add new import function
|
||||
Inc(LookupIndex);
|
||||
if LookupIndex > MAXIMPORTS + MAXIMPORTLIBS then
|
||||
Error('Maximum number of lookup entries exceeded');
|
||||
|
||||
LookupTable[LookupIndex] := NameTableOffset + SizeOf(NameTable[1]) * (ImportIndex - 1);
|
||||
|
||||
Move(Import[ImportIndex].FuncName[1], NameTable[ImportIndex].Name, Length(Import[ImportIndex].FuncName));
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
|
||||
|
||||
procedure FixupImportSection(VirtualAddress: LongInt);
|
||||
var
|
||||
i: Integer;
|
||||
begin
|
||||
with ImportSectionData do
|
||||
begin
|
||||
for i := 1 to NumImportLibs do
|
||||
with DirectoryTable[i] do
|
||||
begin
|
||||
Name := Name + VirtualAddress;
|
||||
FirstThunk := FirstThunk + VirtualAddress;
|
||||
end;
|
||||
|
||||
for i := 1 to NumImports + NumImportLibs do
|
||||
if LookupTable[i] <> 0 then
|
||||
LookupTable[i] := LookupTable[i] + VirtualAddress;
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
|
||||
|
||||
procedure LinkAndWriteProgram(const ExeName: TString);
|
||||
var
|
||||
OutFile: TOutFile;
|
||||
CodeSize, ImportSize, LookupTableOffset: Integer;
|
||||
|
||||
begin
|
||||
if ProgramEntryPoint = 0 then
|
||||
Error('Program entry point not found');
|
||||
|
||||
CodeSize := GetCodeSize;
|
||||
|
||||
FillImportSection(ImportSize, LookupTableOffset);
|
||||
FillHeaders(CodeSize, InitializedGlobalDataSize, UninitializedGlobalDataSize, ImportSize);
|
||||
|
||||
Relocate(IMGBASE + CodeSectionHeader_VirtualAddress,
|
||||
IMGBASE + DataSectionHeader_VirtualAddress,
|
||||
IMGBASE + BSSSectionHeader_VirtualAddress,
|
||||
IMGBASE + ImportSectionHeader_VirtualAddress + LookupTableOffset);
|
||||
|
||||
//FixupImportSection(Headers.ImportSectionHeader.VirtualAddress);
|
||||
|
||||
// Write output file
|
||||
Assign(OutFile, TGenericString(ExeName));
|
||||
Rewrite(OutFile, 1);
|
||||
|
||||
if IOResult <> 0 then
|
||||
Error('Unable to open output file ' + ExeName);
|
||||
|
||||
BlockWrite(OutFile, Headers, SizeOf(Headers));
|
||||
Pad(OutFile, SizeOf(Headers), FILEALIGN);
|
||||
|
||||
BlockWrite(OutFile, Code, CodeSize);
|
||||
Pad(OutFile, CodeSize, FILEALIGN);
|
||||
|
||||
BlockWrite(OutFile, InitializedGlobalData, InitializedGlobalDataSize);
|
||||
Pad(OutFile, InitializedGlobalDataSize, FILEALIGN);
|
||||
{
|
||||
with ImportSectionData do
|
||||
begin
|
||||
BlockWrite(OutFile, DirectoryTable, SizeOf(DirectoryTable[1]) * (NumImportLibs + 1));
|
||||
BlockWrite(OutFile, LibraryNames, SizeOf(LibraryNames[1]) * NumImportLibs);
|
||||
BlockWrite(OutFile, LookupTable, SizeOf(LookupTable[1]) * (NumImports + NumImportLibs));
|
||||
BlockWrite(OutFile, NameTable, SizeOf(NameTable[1]) * NumImports);
|
||||
end;
|
||||
Pad(OutFile, ImportSize, FILEALIGN);
|
||||
}
|
||||
Close(OutFile);
|
||||
end;
|
||||
|
||||
|
||||
end.
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
#SHS
|
||||
rm xdpk.kex
|
||||
../../xdpk.kex xdpk.pas
|
||||
exit
|
||||
File diff suppressed because it is too large.
Load diff
@@ -1,698 +0,0 @@
|
||||
// XD Pascal - a 32-bit compiler for KolibriOS
|
||||
// Copyright (c) 2009-2010, 2019-2020, Vasiliy Tereshkov
|
||||
|
||||
{$I-}
|
||||
{$H-}
|
||||
|
||||
unit Scanner;
|
||||
|
||||
|
||||
interface
|
||||
|
||||
|
||||
uses Common;
|
||||
|
||||
|
||||
var
|
||||
Tok: TToken;
|
||||
|
||||
|
||||
procedure InitializeScanner(const Name: TString);
|
||||
function SaveScanner: Boolean;
|
||||
function RestoreScanner: Boolean;
|
||||
procedure FinalizeScanner;
|
||||
procedure NextTok;
|
||||
procedure CheckTok(ExpectedTokKind: TTokenKind);
|
||||
procedure EatTok(ExpectedTokKind: TTokenKind);
|
||||
procedure AssertIdent;
|
||||
function ScannerFileName: TString;
|
||||
function ScannerLine: Integer;
|
||||
|
||||
|
||||
|
||||
implementation
|
||||
|
||||
|
||||
|
||||
type
|
||||
TBuffer = record
|
||||
Ptr: PCharacter;
|
||||
Size, Pos: Integer;
|
||||
end;
|
||||
|
||||
|
||||
TScannerState = record
|
||||
Token: TToken;
|
||||
FileName: TString;
|
||||
Line: Integer;
|
||||
Buffer: TBuffer;
|
||||
ch, ch2: TCharacter;
|
||||
EndOfUnit: Boolean;
|
||||
end;
|
||||
|
||||
|
||||
const
|
||||
SCANNERSTACKSIZE = 10;
|
||||
|
||||
|
||||
var
|
||||
ScannerState: TScannerState;
|
||||
ScannerStack: array [1..SCANNERSTACKSIZE] of TScannerState;
|
||||
ScannerStackTop: Integer = 0;
|
||||
|
||||
|
||||
const
|
||||
Digits: set of TCharacter = ['0'..'9'];
|
||||
HexDigits: set of TCharacter = ['0'..'9', 'A'..'F'];
|
||||
Spaces: set of TCharacter = [#1..#31, ' '];
|
||||
AlphaNums: set of TCharacter = ['A'..'Z', 'a'..'z', '0'..'9', '_'];
|
||||
|
||||
|
||||
|
||||
|
||||
procedure InitializeScanner(const Name: TString);
|
||||
var
|
||||
F: TInFile;
|
||||
ActualSize: Integer;
|
||||
FolderIndex: Integer;
|
||||
|
||||
begin
|
||||
ScannerState.Buffer.Ptr := nil;
|
||||
|
||||
// First search the source folder, then the units folder, then the folders specified in $UNITPATH
|
||||
FolderIndex := 1;
|
||||
|
||||
repeat
|
||||
Assign(F, TGenericString(Folders[FolderIndex] + Name));
|
||||
Reset(F, 1);
|
||||
if IOResult = 0 then Break;
|
||||
Inc(FolderIndex);
|
||||
until FolderIndex > NumFolders;
|
||||
|
||||
if FolderIndex > NumFolders then
|
||||
Error('Unable to open source file ' + Name);
|
||||
|
||||
with ScannerState do
|
||||
begin
|
||||
FileName := Name;
|
||||
Line := 1;
|
||||
|
||||
with Buffer do
|
||||
begin
|
||||
Size := FileSize(F);
|
||||
Pos := 0;
|
||||
|
||||
GetMem(Ptr, Size);
|
||||
|
||||
ActualSize := 0;
|
||||
BlockRead(F, Ptr^, Size, ActualSize);
|
||||
Close(F);
|
||||
|
||||
if ActualSize <> Size then
|
||||
Error('Unable to read source file ' + Name);
|
||||
end;
|
||||
|
||||
ch := ' ';
|
||||
ch2 := ' ';
|
||||
EndOfUnit := FALSE;
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
|
||||
|
||||
function SaveScanner: Boolean;
|
||||
begin
|
||||
Result := FALSE;
|
||||
if ScannerStackTop < SCANNERSTACKSIZE then
|
||||
begin
|
||||
Inc(ScannerStackTop);
|
||||
ScannerStack[ScannerStackTop] := ScannerState;
|
||||
Result := TRUE;
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
|
||||
|
||||
function RestoreScanner: Boolean;
|
||||
begin
|
||||
Result := FALSE;
|
||||
if ScannerStackTop > 0 then
|
||||
begin
|
||||
ScannerState := ScannerStack[ScannerStackTop];
|
||||
Dec(ScannerStackTop);
|
||||
Tok := ScannerState.Token;
|
||||
Result := TRUE;
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
|
||||
|
||||
procedure FinalizeScanner;
|
||||
begin
|
||||
ScannerState.EndOfUnit := TRUE;
|
||||
with ScannerState.Buffer do
|
||||
if Ptr <> nil then
|
||||
begin
|
||||
FreeMem(Ptr);
|
||||
Ptr := nil;
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
|
||||
|
||||
procedure AppendStrSafe(var s: TString; ch: TCharacter);
|
||||
begin
|
||||
if Length(s) >= MAXSTRLENGTH - 1 then
|
||||
Error('String is too long');
|
||||
s := s + ch;
|
||||
end;
|
||||
|
||||
|
||||
|
||||
|
||||
procedure ReadChar(var ch: TCharacter);
|
||||
begin
|
||||
if ScannerState.ch = #10 then Inc(ScannerState.Line); // End of line found
|
||||
|
||||
ch := #0;
|
||||
with ScannerState.Buffer do
|
||||
if Pos < Size then
|
||||
begin
|
||||
ch := PCharacter(Integer(Ptr) + Pos)^;
|
||||
Inc(Pos);
|
||||
end
|
||||
else
|
||||
ScannerState.EndOfUnit := TRUE;
|
||||
end;
|
||||
|
||||
|
||||
|
||||
|
||||
procedure ReadUppercaseChar(var ch: TCharacter);
|
||||
begin
|
||||
ReadChar(ch);
|
||||
ch := UpCase(ch);
|
||||
end;
|
||||
|
||||
|
||||
|
||||
|
||||
procedure ReadLiteralChar(var ch: TCharacter);
|
||||
begin
|
||||
ReadChar(ch);
|
||||
if (ch = #0) or (ch = #10) then
|
||||
Error('Unterminated string');
|
||||
end;
|
||||
|
||||
|
||||
|
||||
|
||||
procedure ReadSingleLineComment;
|
||||
begin
|
||||
with ScannerState do
|
||||
while (ch <> #10) and not EndOfUnit do
|
||||
ReadChar(ch);
|
||||
end;
|
||||
|
||||
|
||||
|
||||
|
||||
procedure ReadMultiLineComment;
|
||||
begin
|
||||
with ScannerState do
|
||||
while (ch <> '}') and not EndOfUnit do
|
||||
ReadChar(ch);
|
||||
end;
|
||||
|
||||
|
||||
|
||||
|
||||
procedure ReadDirective;
|
||||
var
|
||||
Text: TString;
|
||||
begin
|
||||
with ScannerState do
|
||||
begin
|
||||
Text := '';
|
||||
repeat
|
||||
AppendStrSafe(Text, ch);
|
||||
ReadUppercaseChar(ch);
|
||||
until not (ch in AlphaNums);
|
||||
|
||||
if Text = '$APPTYPE' then // Console/GUI application type directive
|
||||
begin
|
||||
Text := '';
|
||||
ReadChar(ch);
|
||||
while (ch <> '}') and not EndOfUnit do
|
||||
begin
|
||||
if (ch = #0) or (ch > ' ') then
|
||||
AppendStrSafe(Text, UpCase(ch));
|
||||
ReadChar(ch);
|
||||
end;
|
||||
|
||||
if Text = 'CONSOLE' then
|
||||
IsConsoleProgram := TRUE
|
||||
else if Text = 'GUI' then
|
||||
IsConsoleProgram := FALSE
|
||||
else
|
||||
Error('Unknown application type ' + Text);
|
||||
end
|
||||
|
||||
else if Text = '$UNITPATH' then // Unit path directive
|
||||
begin
|
||||
Text := '';
|
||||
ReadChar(ch);
|
||||
while (ch <> '}') and not EndOfUnit do
|
||||
begin
|
||||
if (ch = #0) or (ch > ' ') then
|
||||
AppendStrSafe(Text, UpCase(ch));
|
||||
ReadChar(ch);
|
||||
end;
|
||||
|
||||
Inc(NumFolders);
|
||||
if NumFolders > MAXFOLDERS then
|
||||
Error('Maximum number of unit paths exceeded');
|
||||
Folders[NumFolders] := Folders[1] + Text;
|
||||
end
|
||||
|
||||
else // All other directives are ignored
|
||||
ReadMultiLineComment;
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
|
||||
|
||||
procedure ReadHexadecimalNumber;
|
||||
var
|
||||
Num, Digit: Integer;
|
||||
NumFound: Boolean;
|
||||
begin
|
||||
with ScannerState do
|
||||
begin
|
||||
Num := 0;
|
||||
|
||||
NumFound := FALSE;
|
||||
while ch in HexDigits do
|
||||
begin
|
||||
if Num and $F0000000 <> 0 then
|
||||
Error('Numeric constant is too large');
|
||||
|
||||
if ch in Digits then
|
||||
Digit := Ord(ch) - Ord('0')
|
||||
else
|
||||
Digit := Ord(ch) - Ord('A') + 10;
|
||||
|
||||
Num := Num shl 4 or Digit;
|
||||
NumFound := TRUE;
|
||||
ReadUppercaseChar(ch);
|
||||
end;
|
||||
|
||||
if not NumFound then
|
||||
Error('Hexadecimal constant is not found');
|
||||
|
||||
Token.Kind := INTNUMBERTOK;
|
||||
Token.OrdValue := Num;
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
|
||||
|
||||
procedure ReadDecimalNumber;
|
||||
var
|
||||
Num, Expon, Digit: Integer;
|
||||
Frac, FracWeight: Double;
|
||||
NegExpon, RangeFound, ExponFound: Boolean;
|
||||
begin
|
||||
with ScannerState do
|
||||
begin
|
||||
Num := 0;
|
||||
Frac := 0;
|
||||
Expon := 0;
|
||||
NegExpon := FALSE;
|
||||
|
||||
while ch in Digits do
|
||||
begin
|
||||
Digit := Ord(ch) - Ord('0');
|
||||
|
||||
if Num > (HighBound(INTEGERTYPEINDEX) - Digit) div 10 then
|
||||
Error('Numeric constant is too large');
|
||||
|
||||
Num := 10 * Num + Digit;
|
||||
ReadUppercaseChar(ch);
|
||||
end;
|
||||
|
||||
if (ch <> '.') and (ch <> 'E') then // Integer number
|
||||
begin
|
||||
Token.Kind := INTNUMBERTOK;
|
||||
Token.OrdValue := Num;
|
||||
end
|
||||
else
|
||||
begin
|
||||
|
||||
// Check for '..' token
|
||||
RangeFound := FALSE;
|
||||
if ch = '.' then
|
||||
begin
|
||||
ReadUppercaseChar(ch2);
|
||||
if ch2 = '.' then // Integer number followed by '..' token
|
||||
begin
|
||||
Token.Kind := INTNUMBERTOK;
|
||||
Token.OrdValue := Num;
|
||||
RangeFound := TRUE;
|
||||
end;
|
||||
if not EndOfUnit then Dec(Buffer.Pos);
|
||||
end; // if ch = '.'
|
||||
|
||||
if not RangeFound then // Fractional number
|
||||
begin
|
||||
|
||||
// Check for fractional part
|
||||
if ch = '.' then
|
||||
begin
|
||||
FracWeight := 0.1;
|
||||
ReadUppercaseChar(ch);
|
||||
|
||||
while ch in Digits do
|
||||
begin
|
||||
Digit := Ord(ch) - Ord('0');
|
||||
Frac := Frac + FracWeight * Digit;
|
||||
FracWeight := FracWeight / 10;
|
||||
ReadUppercaseChar(ch);
|
||||
end;
|
||||
end; // if ch = '.'
|
||||
|
||||
// Check for exponent
|
||||
if ch = 'E' then
|
||||
begin
|
||||
ReadUppercaseChar(ch);
|
||||
|
||||
// Check for exponent sign
|
||||
if ch = '+' then
|
||||
ReadUppercaseChar(ch)
|
||||
else if ch = '-' then
|
||||
begin
|
||||
NegExpon := TRUE;
|
||||
ReadUppercaseChar(ch);
|
||||
end;
|
||||
|
||||
ExponFound := FALSE;
|
||||
while ch in Digits do
|
||||
begin
|
||||
Digit := Ord(ch) - Ord('0');
|
||||
Expon := 10 * Expon + Digit;
|
||||
ReadUppercaseChar(ch);
|
||||
ExponFound := TRUE;
|
||||
end;
|
||||
|
||||
if not ExponFound then
|
||||
Error('Exponent is not found');
|
||||
|
||||
if NegExpon then Expon := -Expon;
|
||||
end; // if ch = 'E'
|
||||
|
||||
Token.Kind := REALNUMBERTOK;
|
||||
Token.RealValue := (Num + Frac) * exp(Expon * ln(10));
|
||||
end; // if not RangeFound
|
||||
end; // else
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
|
||||
|
||||
procedure ReadNumber;
|
||||
begin
|
||||
with ScannerState do
|
||||
if ch = '$' then
|
||||
begin
|
||||
ReadUppercaseChar(ch);
|
||||
ReadHexadecimalNumber;
|
||||
end
|
||||
else
|
||||
ReadDecimalNumber;
|
||||
end;
|
||||
|
||||
|
||||
|
||||
|
||||
procedure ReadCharCode;
|
||||
begin
|
||||
with ScannerState do
|
||||
begin
|
||||
ReadUppercaseChar(ch);
|
||||
|
||||
if not (ch in Digits + ['$']) then
|
||||
Error('Character code is not found');
|
||||
|
||||
ReadNumber;
|
||||
|
||||
if (Token.Kind = REALNUMBERTOK) or (Token.OrdValue < 0) or (Token.OrdValue > 255) then
|
||||
Error('Illegal character code');
|
||||
|
||||
Token.Kind := CHARLITERALTOK;
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
|
||||
|
||||
procedure ReadKeywordOrIdentifier;
|
||||
var
|
||||
Text, NonUppercaseText: TString;
|
||||
CurToken: TTokenKind;
|
||||
begin
|
||||
with ScannerState do
|
||||
begin
|
||||
Text := '';
|
||||
NonUppercaseText := '';
|
||||
|
||||
repeat
|
||||
AppendStrSafe(NonUppercaseText, ch);
|
||||
ch := UpCase(ch);
|
||||
AppendStrSafe(Text, ch);
|
||||
ReadChar(ch);
|
||||
until not (ch in AlphaNums);
|
||||
|
||||
CurToken := GetKeyword(Text);
|
||||
if CurToken <> EMPTYTOK then // Keyword found
|
||||
Token.Kind := CurToken
|
||||
else
|
||||
begin // Identifier found
|
||||
Token.Kind := IDENTTOK;
|
||||
Token.Name := Text;
|
||||
Token.NonUppercaseName := NonUppercaseText;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
|
||||
|
||||
procedure ReadCharOrStringLiteral;
|
||||
var
|
||||
Text: TString;
|
||||
EndOfLiteral: Boolean;
|
||||
begin
|
||||
with ScannerState do
|
||||
begin
|
||||
Text := '';
|
||||
EndOfLiteral := FALSE;
|
||||
|
||||
repeat
|
||||
ReadLiteralChar(ch);
|
||||
if ch <> '''' then
|
||||
AppendStrSafe(Text, ch)
|
||||
else
|
||||
begin
|
||||
ReadChar(ch2);
|
||||
if ch2 = '''' then // Apostrophe character found
|
||||
AppendStrSafe(Text, ch)
|
||||
else
|
||||
begin
|
||||
if not EndOfUnit then Dec(Buffer.Pos); // Discard ch2
|
||||
EndOfLiteral := TRUE;
|
||||
end;
|
||||
end;
|
||||
until EndOfLiteral;
|
||||
|
||||
if Length(Text) = 1 then
|
||||
begin
|
||||
Token.Kind := CHARLITERALTOK;
|
||||
Token.OrdValue := Ord(Text[1]);
|
||||
end
|
||||
else
|
||||
begin
|
||||
Token.Kind := STRINGLITERALTOK;
|
||||
Token.Name := Text;
|
||||
Token.StrLength := Length(Text);
|
||||
DefineStaticString(Text, Token.StrAddress);
|
||||
end;
|
||||
|
||||
ReadUppercaseChar(ch);
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
|
||||
|
||||
procedure NextTok;
|
||||
begin
|
||||
with ScannerState do
|
||||
begin
|
||||
Token.Kind := EMPTYTOK;
|
||||
|
||||
// Skip spaces, comments, directives
|
||||
while (ch in Spaces) or (ch = '{') or (ch = '/') do
|
||||
begin
|
||||
if ch = '{' then // Multi-line comment or directive
|
||||
begin
|
||||
ReadUppercaseChar(ch);
|
||||
if ch = '$' then ReadDirective else ReadMultiLineComment;
|
||||
end
|
||||
else if ch = '/' then
|
||||
begin
|
||||
ReadUppercaseChar(ch2);
|
||||
if ch2 = '/' then
|
||||
ReadSingleLineComment // Double-line comment
|
||||
else
|
||||
begin
|
||||
if not EndOfUnit then Dec(Buffer.Pos); // Discard ch2
|
||||
Break;
|
||||
end;
|
||||
end;
|
||||
ReadChar(ch);
|
||||
end;
|
||||
|
||||
// Read token
|
||||
case ch of
|
||||
'0'..'9', '$':
|
||||
ReadNumber;
|
||||
'#':
|
||||
ReadCharCode;
|
||||
'A'..'Z', 'a'..'z', '_':
|
||||
ReadKeywordOrIdentifier;
|
||||
'''':
|
||||
ReadCharOrStringLiteral;
|
||||
':': // Single- or double-character tokens
|
||||
begin
|
||||
Token.Kind := COLONTOK;
|
||||
ReadUppercaseChar(ch);
|
||||
if ch = '=' then
|
||||
begin
|
||||
Token.Kind := ASSIGNTOK;
|
||||
ReadUppercaseChar(ch);
|
||||
end;
|
||||
end;
|
||||
'>':
|
||||
begin
|
||||
Token.Kind := GTTOK;
|
||||
ReadUppercaseChar(ch);
|
||||
if ch = '=' then
|
||||
begin
|
||||
Token.Kind := GETOK;
|
||||
ReadUppercaseChar(ch);
|
||||
end;
|
||||
end;
|
||||
'<':
|
||||
begin
|
||||
Token.Kind := LTTOK;
|
||||
ReadUppercaseChar(ch);
|
||||
if ch = '=' then
|
||||
begin
|
||||
Token.Kind := LETOK;
|
||||
ReadUppercaseChar(ch);
|
||||
end
|
||||
else if ch = '>' then
|
||||
begin
|
||||
Token.Kind := NETOK;
|
||||
ReadUppercaseChar(ch);
|
||||
end;
|
||||
end;
|
||||
'.':
|
||||
begin
|
||||
Token.Kind := PERIODTOK;
|
||||
ReadUppercaseChar(ch);
|
||||
if ch = '.' then
|
||||
begin
|
||||
Token.Kind := RANGETOK;
|
||||
ReadUppercaseChar(ch);
|
||||
end;
|
||||
end
|
||||
else // Double-character tokens
|
||||
case ch of
|
||||
'=': Token.Kind := EQTOK;
|
||||
',': Token.Kind := COMMATOK;
|
||||
';': Token.Kind := SEMICOLONTOK;
|
||||
'(': Token.Kind := OPARTOK;
|
||||
')': Token.Kind := CPARTOK;
|
||||
'*': Token.Kind := MULTOK;
|
||||
'/': Token.Kind := DIVTOK;
|
||||
'+': Token.Kind := PLUSTOK;
|
||||
'-': Token.Kind := MINUSTOK;
|
||||
'^': Token.Kind := DEREFERENCETOK;
|
||||
'@': Token.Kind := ADDRESSTOK;
|
||||
'[': Token.Kind := OBRACKETTOK;
|
||||
']': Token.Kind := CBRACKETTOK
|
||||
else
|
||||
Error('Unexpected character or end of file');
|
||||
end; // case
|
||||
|
||||
ReadChar(ch);
|
||||
end; // case
|
||||
end;
|
||||
|
||||
Tok := ScannerState.Token;
|
||||
end; // NextTok
|
||||
|
||||
|
||||
|
||||
|
||||
procedure CheckTok(ExpectedTokKind: TTokenKind);
|
||||
begin
|
||||
with ScannerState do
|
||||
if Token.Kind <> ExpectedTokKind then
|
||||
Error(GetTokSpelling(ExpectedTokKind) + ' expected but ' + GetTokSpelling(Token.Kind) + ' found');
|
||||
end;
|
||||
|
||||
|
||||
|
||||
|
||||
procedure EatTok(ExpectedTokKind: TTokenKind);
|
||||
begin
|
||||
CheckTok(ExpectedTokKind);
|
||||
NextTok;
|
||||
end;
|
||||
|
||||
|
||||
|
||||
|
||||
procedure AssertIdent;
|
||||
begin
|
||||
with ScannerState do
|
||||
if Token.Kind <> IDENTTOK then
|
||||
Error('Identifier expected but ' + GetTokSpelling(Token.Kind) + ' found');
|
||||
end;
|
||||
|
||||
|
||||
|
||||
|
||||
function ScannerFileName: TString;
|
||||
begin
|
||||
Result := ScannerState.FileName;
|
||||
end;
|
||||
|
||||
|
||||
|
||||
|
||||
function ScannerLine: Integer;
|
||||
begin
|
||||
Result := ScannerState.Line;
|
||||
end;
|
||||
|
||||
end.
|
||||
@@ -1,128 +0,0 @@
|
||||
// XD Pascal - a 32-bit compiler for KolibriOS
|
||||
// Copyright (c) 2009-2010, 2019-2020, Vasiliy Tereshkov
|
||||
|
||||
{$APPTYPE CONSOLE}
|
||||
{$I-}
|
||||
{$H-}
|
||||
|
||||
program XDPK;
|
||||
|
||||
|
||||
uses SysUtils, Common, Scanner, Parser, CodeGen, Linker;
|
||||
|
||||
|
||||
|
||||
|
||||
procedure SplitPath(const Path: TString; var Folder, Name, Ext: TString);
|
||||
var
|
||||
DotPos, SlashPos, i: Integer;
|
||||
begin
|
||||
Folder := '';
|
||||
Name := Path;
|
||||
Ext := '';
|
||||
|
||||
DotPos := 0;
|
||||
SlashPos := 0;
|
||||
|
||||
for i := Length(Path) downto 1 do
|
||||
if (Path[i] = '.') and (DotPos = 0) then
|
||||
DotPos := i
|
||||
else if (Path[i] = '/') and (SlashPos = 0) then
|
||||
SlashPos := i;
|
||||
|
||||
if DotPos > 0 then
|
||||
begin
|
||||
Name := Copy(Path, 1, DotPos - 1);
|
||||
Ext := Copy(Path, DotPos, Length(Path) - DotPos + 1);
|
||||
end;
|
||||
|
||||
if SlashPos > 0 then
|
||||
begin
|
||||
Folder := Copy(Path, 1, SlashPos);
|
||||
Name := Copy(Path, SlashPos + 1, Length(Name) - SlashPos);
|
||||
end;
|
||||
|
||||
end;
|
||||
|
||||
|
||||
|
||||
|
||||
procedure NoticeProc(ClassInstance: Pointer; const Msg: TString);
|
||||
begin
|
||||
WriteLn(Msg);
|
||||
end;
|
||||
|
||||
|
||||
|
||||
|
||||
procedure WarningProc(ClassInstance: Pointer; const Msg: TString);
|
||||
begin
|
||||
if NumUnits >= 1 then
|
||||
Notice(ScannerFileName + ' (' + IntToStr(ScannerLine) + ') Warning: ' + Msg)
|
||||
else
|
||||
Notice('Warning: ' + Msg);
|
||||
end;
|
||||
|
||||
|
||||
|
||||
|
||||
procedure ErrorProc(ClassInstance: Pointer; const Msg: TString);
|
||||
begin
|
||||
if NumUnits >= 1 then
|
||||
Notice(ScannerFileName + ' (' + IntToStr(ScannerLine) + ') Error: ' + Msg)
|
||||
else
|
||||
Notice('Error: ' + Msg);
|
||||
|
||||
repeat FinalizeScanner until not RestoreScanner;
|
||||
FinalizeCommon;
|
||||
Halt(1);
|
||||
end;
|
||||
|
||||
|
||||
|
||||
|
||||
var
|
||||
CompilerPath, CompilerFolder, CompilerName, CompilerExt,
|
||||
PasPath, PasFolder, PasName, PasExt,
|
||||
ExePath: TString;
|
||||
|
||||
|
||||
|
||||
begin
|
||||
SetWriteProcs(nil, @NoticeProc, @WarningProc, @ErrorProc);
|
||||
|
||||
Notice('XD Pascal for KolibriOS ' + VERSION);
|
||||
Notice('Copyright (c) 2009-2010, 2019-2020, Vasiliy Tereshkov');
|
||||
|
||||
if ParamCount < 1 then
|
||||
begin
|
||||
Notice('Usage: xdpk <file.pas>');
|
||||
Halt(1);
|
||||
end;
|
||||
|
||||
CompilerPath := TString(ParamStr(0));
|
||||
SplitPath(CompilerPath, CompilerFolder, CompilerName, CompilerExt);
|
||||
|
||||
PasPath := TString(ParamStr(1));
|
||||
SplitPath(PasPath, PasFolder, PasName, PasExt);
|
||||
|
||||
InitializeCommon;
|
||||
InitializeLinker;
|
||||
InitializeCodeGen;
|
||||
|
||||
Folders[1] := PasFolder;
|
||||
Folders[2] := CompilerFolder + 'units/';
|
||||
NumFolders := 2;
|
||||
|
||||
CompileProgramOrUnit('system.pas');
|
||||
CompileProgramOrUnit(PasName + PasExt);
|
||||
|
||||
ExePath := PasFolder + PasName + '.kex';
|
||||
LinkAndWriteProgram(ExePath);
|
||||
|
||||
Notice('Complete. Code size: ' + IntToStr(GetCodeSize) + ' bytes. Data size: ' + IntToStr(InitializedGlobalDataSize + UninitializedGlobalDataSize) + ' bytes');
|
||||
|
||||
repeat FinalizeScanner until not RestoreScanner;
|
||||
FinalizeCommon;
|
||||
end.
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
if exist xdpk.kex del xdpk.kex
|
||||
..\..\xdpk xdpk.pas
|
||||
if exist xdpk.kex ..\..\kpack xdpk.kex
|
||||
pause
|
||||
|
||||
@@ -1,87 +0,0 @@
|
||||
program Draw_Scaled_PNG_Image;
|
||||
|
||||
uses
|
||||
KolibriOS, LibImg;
|
||||
|
||||
var
|
||||
WndLeft, WndTop, WndWidth, WndHeight: Integer;
|
||||
|
||||
ImageToDraw: PImage; // шчюсЁрцхэшх, ъюЄюЁюх сєфхь ЁшёютрЄ№
|
||||
|
||||
// яЁюсєхь чруЁєчшЄ№ Їрщы шчюсЁрцхэш , фхъюфшЁютрЄ№ ш ьрё°ЄрсшЁютрЄ№
|
||||
function OpenImageFile(FilePath: PAnsiChar): PImage;
|
||||
var
|
||||
FileAttributes: TFileAttributes;
|
||||
BytesRead: Integer;
|
||||
imgFile: Pointer;
|
||||
imgFileSize: Integer;
|
||||
imgData, imgScaled: PImage;
|
||||
begin
|
||||
Result := nil;
|
||||
// хёыш Їрщы фюёЄєяхэ
|
||||
if GetFileAttributes(FilePath, FileAttributes) = 0 then
|
||||
begin
|
||||
// єчэр╕ь ЁрчьхЁ Їрщыр т срщЄрї
|
||||
imgFileSize := FileAttributes.SizeLo;
|
||||
// т√фхы хь ярь Є№ фы ўЄхэш Єєфр ¤Єюую Їрщыр
|
||||
GetMem(imgFile, imgFileSize);
|
||||
// ўшЄрхь Їрщы
|
||||
ReadFile(FilePath, PAnsiChar(imgFile)^, imgFileSize, 0, 0, BytesRead);
|
||||
// яЁюсєхь фхъюфшЁютрЄ№ Їрщы шчюсЁрцхэш
|
||||
imgData := img_decode(imgFile, imgFileSize, nil);
|
||||
// юётюсюцфрхь т√фхыхээє■ яюф Їрщы ярь Є№
|
||||
FreeMem(imgFile);
|
||||
// хёыш єфрыюё№ фхъюфшЁютрЄ№ Їрщы шчюсЁрцхэш
|
||||
if imgData <> nil then
|
||||
begin
|
||||
// хёыш эхяюффхЁцштрхьр сшсышюЄхъющ уыєсшэр ЎтхЄр
|
||||
if not (imgData^.ImageType in [IMAGE_BPP24, IMAGE_BPP32, IMAGE_BPP8G]) then
|
||||
begin
|
||||
// ъюэтхЁЄшЁєхь т шчюсЁрцхэшх ё яюффхЁцштрхьющ уыєсшэющ
|
||||
imgScaled := img_convert(imgData, nil, IMAGE_BPP24, 0, 0);
|
||||
// єэшўЄюцрхь шёїюфэюх шчюсЁрцхэшх
|
||||
img_destroy(imgData);
|
||||
imgData := imgScaled;
|
||||
end;
|
||||
// яЁюсєхь ьрё°ЄрсшЁютрЄ№ т эют√щ ЁрчьхЁ 200x150
|
||||
imgScaled := img_scale(imgData, 0, 0, imgData^.Width, imgData^.Height,
|
||||
nil, LIBIMG_SCALE_STRETCH, LIBIMG_INTER_DEFAULT, 200, 150);
|
||||
Result := imgScaled;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
begin
|
||||
//SetAppDirAsCurrent;
|
||||
|
||||
LibImg_initialization;
|
||||
|
||||
with GetScreenSize do
|
||||
begin
|
||||
WndWidth := Width div 4;
|
||||
WndHeight := Height div 4;
|
||||
WndLeft := (Width - WndWidth) div 2;
|
||||
WndTop := (Height - WndHeight) div 2;
|
||||
end;
|
||||
|
||||
ImageToDraw := OpenImageFile('./Background.png');
|
||||
|
||||
while True do
|
||||
case WaitEvent of
|
||||
REDRAW_EVENT:
|
||||
begin
|
||||
BeginDraw;
|
||||
DrawWindow(WndLeft, WndTop, WndWidth, WndHeight, 'Draw Scaled PNG Image', $00FFFFFF,
|
||||
WS_SKINNED_FIXED + WS_CLIENT_COORDS + WS_CAPTION, CAPTION_MOVABLE);
|
||||
// хёыш яюыєўшыюё№ ьрё°ЄрсшЁютрЄ№, Єю Ёшёєхь хую т Єюўъх (10, 5)
|
||||
if ImageToDraw <> nil then
|
||||
img_draw(ImageToDraw, 10, 5, $ffffffff, $ffffffff, 0, 0);
|
||||
EndDraw;
|
||||
end;
|
||||
KEY_EVENT:
|
||||
GetKey;
|
||||
BUTTON_EVENT:
|
||||
if GetButton.ID = 1 then
|
||||
Exit;
|
||||
end;
|
||||
end.
|
||||
@@ -1,12 +0,0 @@
|
||||
{$APPTYPE CONSOLE}
|
||||
|
||||
program EnterNumber;
|
||||
|
||||
var
|
||||
Number: LongInt;
|
||||
|
||||
begin
|
||||
Write('Enter Number please:');
|
||||
ReadLn(Number);
|
||||
WriteLn('You entered "', Number, '"');
|
||||
end.
|
||||
@@ -1,48 +0,0 @@
|
||||
program ExpSinGraph_CRT;
|
||||
|
||||
{ example from K. Jensen, N. Wirth "Pascal User Manual and Report" }
|
||||
|
||||
uses
|
||||
CRT;
|
||||
|
||||
const
|
||||
d = 1 / 16; // 16 lines for interval [x, x + 1]
|
||||
s = 32 / 1.5; // 32 character widths for interval [y, y + 1]
|
||||
h = 34; // character position of x-axis
|
||||
c = 2 * PI;
|
||||
lim = 32;
|
||||
|
||||
var
|
||||
i, n: Integer;
|
||||
x, y: Extended;
|
||||
|
||||
Colors: array [0..14] of Byte = (LightRed, Yellow, LightGreen, LightCyan, LightBlue,
|
||||
LightMagenta, White, LightGray, DarkGray, Magenta, Blue, Cyan, Green, Brown, Red);
|
||||
|
||||
ColorIndex: Integer = 0;
|
||||
|
||||
procedure SwitchColor;
|
||||
begin
|
||||
TextColor(Colors[ColorIndex]);
|
||||
Inc(ColorIndex);
|
||||
if ColorIndex > High(Colors) then
|
||||
ColorIndex := Low(Colors);
|
||||
end;
|
||||
|
||||
begin
|
||||
|
||||
CRT_initialization();
|
||||
|
||||
for i := 0 to lim do
|
||||
begin
|
||||
x := d * i;
|
||||
y := Exp(-x) * Sin(c * x);
|
||||
n := Round(s * y) + h;
|
||||
SwitchColor();
|
||||
repeat
|
||||
Write(' ');
|
||||
Dec(n);
|
||||
until n = 0;
|
||||
WriteLn('*');
|
||||
end;
|
||||
end.
|
||||
@@ -1,24 +0,0 @@
|
||||
program GetIPAddr;
|
||||
|
||||
uses
|
||||
KolibriOS, Network;
|
||||
|
||||
var
|
||||
AddrInfo: PAddrInfo;
|
||||
InputStr: string;
|
||||
|
||||
begin
|
||||
Network_initialization;
|
||||
|
||||
while True do
|
||||
begin
|
||||
Write('Input host:'); ReadLn(InputStr);
|
||||
if getaddrinfo(InputStr, nil, nil, AddrInfo) = 0{success} then
|
||||
WriteLn(PString(inet_ntoa(AddrInfo^.ai_addr^.sin_addr))^)
|
||||
else
|
||||
WriteLn('Error!');
|
||||
freeaddrinfo(AddrInfo);
|
||||
Write('Continue?[Y/N]:'); ReadLn(InputStr);
|
||||
if UpCase(InputStr[1]) = 'N' then Exit;
|
||||
end;
|
||||
end.
|
||||
@@ -1,49 +0,0 @@
|
||||
program INI_File_Read;
|
||||
|
||||
uses
|
||||
LibINI;
|
||||
|
||||
procedure IniKeyCallback(FileName, SectionName, KeyName, KeyValue: PAnsiChar) stdcall;
|
||||
begin
|
||||
Write(' ', PString(KeyName)^);
|
||||
Write(' = ');
|
||||
WriteLn(PString(KeyValue)^);
|
||||
end;
|
||||
|
||||
procedure IniSectionCallback(FileName, SectionName: PAnsiChar) stdcall;
|
||||
begin
|
||||
WriteLn(PString(SectionName)^);
|
||||
ini_enum_keys(FileName, SectionName, @IniKeyCallback);
|
||||
end;
|
||||
|
||||
const
|
||||
FILE_PATH = '/sys/settings/system.ini';
|
||||
|
||||
var
|
||||
SystemLang: array [0..255] of AnsiChar;
|
||||
MouseSpeed: Integer;
|
||||
|
||||
begin
|
||||
LibINI_initialization;
|
||||
|
||||
WriteLn('Hello, this is a test for LibINI!');
|
||||
WriteLn;
|
||||
ini_enum_sections(FILE_PATH, @IniSectionCallback);
|
||||
WriteLn;
|
||||
|
||||
WriteLn('Try to get system.language and mouse.speed:');
|
||||
|
||||
if ini_get_str(FILE_PATH, 'system', 'language', SystemLang, SizeOf(SystemLang), 'ru') = 0 then
|
||||
WriteLn('Lang = "', SystemLang, '"')
|
||||
else
|
||||
WriteLn('Lang not found, used default "', SystemLang , '"');
|
||||
|
||||
MouseSpeed := ini_get_int(FILE_PATH, 'mouse', 'speed', -1);
|
||||
if MouseSpeed <> -1 then
|
||||
WriteLn('MouseSpeed = "', MouseSpeed, '"')
|
||||
else
|
||||
begin
|
||||
MouseSpeed := 5;
|
||||
WriteLn('MouseSpeed not found, used default "', MouseSpeed , '"');
|
||||
end;
|
||||
end.
|
||||
@@ -1,22 +0,0 @@
|
||||
program Just_Window;
|
||||
|
||||
uses
|
||||
KolibriOS;
|
||||
|
||||
begin
|
||||
while True do
|
||||
case WaitEvent of
|
||||
REDRAW_EVENT:
|
||||
begin
|
||||
BeginDraw;
|
||||
DrawWindow(300, 200, 350, 250, 'Hello from XDPascal!', $00D5E3F1,
|
||||
WS_SKINNED_SIZABLE + WS_CLIENT_COORDS + WS_CAPTION, CAPTION_MOVABLE);
|
||||
EndDraw;
|
||||
end;
|
||||
KEY_EVENT:
|
||||
GetKey;
|
||||
BUTTON_EVENT:
|
||||
if GetButton.ID = 1 then
|
||||
Exit;
|
||||
end;
|
||||
end.
|
||||
@@ -1,38 +0,0 @@
|
||||
#SHS
|
||||
rm ClrEOL_CRT.kex
|
||||
rm CmdLineArgs.kex
|
||||
rm Draw_Scaled_PNG_Image.kex
|
||||
rm EnterNumber.kex
|
||||
rm ExpSinGraph_CRT.kex
|
||||
rm factor.kex
|
||||
rm GetIPAddr.kex
|
||||
rm hello.kex
|
||||
rm INI_file_Read.kex
|
||||
rm Just_Window.kex
|
||||
rm Mouse_Test.kex
|
||||
rm Pyramid_TinyGL.kex
|
||||
rm raytracer.kex
|
||||
rm Select_Color_in_ColorDialog.kex
|
||||
rm Select_File_in_OpenDialog.kex
|
||||
rm Sierpinski.kex
|
||||
rm sort.kex
|
||||
rm SpiralMat.kex
|
||||
../xdpk.kex ClrEOL_CRT.pas
|
||||
../xdpk.kex CmdLineArgs.pas
|
||||
../xdpk.kex Draw_Scaled_PNG_Image.pas
|
||||
../xdpk.kex EnterNumber.pas
|
||||
../xdpk.kex ExpSinGraph_CRT.pas
|
||||
../xdpk.kex factor.pas
|
||||
../xdpk.kex GetIPAddr.pas
|
||||
../xdpk.kex hello.pas
|
||||
../xdpk.kex INI_file_Read.pas
|
||||
../xdpk.kex Just_Window.pas
|
||||
../xdpk.kex Mouse_Test.pas
|
||||
../xdpk.kex Pyramid_TinyGL.pas
|
||||
../xdpk.kex raytracer.pas
|
||||
../xdpk.kex Select_Color_in_ColorDialog.pas
|
||||
../xdpk.kex Select_File_in_OpenDialog.pas
|
||||
../xdpk.kex Sierpinski.pas
|
||||
../xdpk.kex sort.pas
|
||||
../xdpk.kex SpiralMat.pas
|
||||
exit
|
||||
@@ -1,74 +0,0 @@
|
||||
program Mouse_Test;
|
||||
|
||||
uses
|
||||
KolibriOS;
|
||||
|
||||
const
|
||||
MY_BUTTON = 1000;
|
||||
|
||||
var
|
||||
WndLeft, WndTop, WndWidth, WndHeight: Integer;
|
||||
|
||||
TxtClickResult: string = 'Yet not clicked.';
|
||||
|
||||
procedure On_Redraw;
|
||||
begin
|
||||
BeginDraw;
|
||||
DrawWindow(300, 200, 350, 250, 'Mouse test.', $00D5E3F1,
|
||||
WS_SKINNED_SIZABLE + WS_CLIENT_COORDS + WS_CAPTION, CAPTION_MOVABLE);
|
||||
DrawButton(10, 20, 50, 30, $0075D3F1, 0, MY_BUTTON);
|
||||
DrawText(20, 55, 'Click on window', $00AF4F3F, 0,
|
||||
DT_CP866_8X16 + DT_TRANSPARENT_FILL + DT_ZSTRING, 0);
|
||||
DrawText(20, 70, 'or click on button', $003F4FAF, 0,
|
||||
DT_CP866_8X16 + DT_TRANSPARENT_FILL + DT_ZSTRING, 0);
|
||||
DrawText(15, 90, TxtClickResult, $001F7F1F, 0,
|
||||
DT_CP866_8X16 + DT_TRANSPARENT_FILL, Length(TxtClickResult));
|
||||
EndDraw;
|
||||
end;
|
||||
|
||||
begin
|
||||
with GetScreenSize do
|
||||
begin
|
||||
WndWidth := Width div 2;
|
||||
WndHeight := Height div 2;
|
||||
WndLeft := (Width - WndWidth) div 2;
|
||||
WndTop := (Height - WndHeight) div 2;
|
||||
end;
|
||||
|
||||
SetEventMask(EM_REDRAW + EM_BUTTON + EM_KEY + EM_MOUSE);
|
||||
|
||||
while True do
|
||||
case WaitEvent of
|
||||
REDRAW_EVENT:
|
||||
On_Redraw;
|
||||
KEY_EVENT:
|
||||
GetKey;
|
||||
MOUSE_EVENT:
|
||||
begin
|
||||
case GetMouseButtons of
|
||||
1: if GetWindowMousePos.X > 100 then
|
||||
TxtClickResult := 'Left mouse button down(X > 100).'
|
||||
else
|
||||
TxtClickResult := 'Left mouse button down(X <= 100).';
|
||||
2: TxtClickResult := 'Right mouse button down.';
|
||||
4: TxtClickResult := 'Middle mouse button down.';
|
||||
end;
|
||||
On_Redraw;
|
||||
end;
|
||||
BUTTON_EVENT:
|
||||
with GetButton do
|
||||
case ID of
|
||||
1: Exit;
|
||||
MY_BUTTON:
|
||||
begin
|
||||
case MouseButton of
|
||||
0: TxtClickResult := 'Button clicked by left mouse button.';
|
||||
2: TxtClickResult := 'Button clicked by right mouse button.';
|
||||
4: TxtClickResult := 'Button clicked by middle mouse button.';
|
||||
end;
|
||||
On_Redraw;
|
||||
end;
|
||||
end;
|
||||
|
||||
end;
|
||||
end.
|
||||
@@ -1,104 +0,0 @@
|
||||
program Pyramid_TinyGL;
|
||||
|
||||
uses
|
||||
KolibriOS, TinyGL;
|
||||
|
||||
var
|
||||
CTX: TKOSGLContext;
|
||||
Angle: GLFloat = 0;
|
||||
Speed: GLFloat = 3.5;
|
||||
|
||||
WndLeft, WndTop, WndWidth, WndHeight: Integer;
|
||||
|
||||
procedure Perspective(fovY, Aspect, zNear, zFar: GLDouble);
|
||||
var
|
||||
fW, fH, fovYPI360: GLDouble;
|
||||
M: array[0..15] of GLFloat;
|
||||
begin
|
||||
FillChar(M, SizeOf(M), #0);
|
||||
fovYPI360 := fovY * PI / 360;
|
||||
fH := Sin(fovYPI360) * zNear / Cos(fovYPI360);
|
||||
fW := fH * Aspect;
|
||||
M[0] := zNear / fW;
|
||||
M[5] := zNear / fH;
|
||||
M[10] := -(zFar + zNear) / (zFar - zNear);
|
||||
M[11] := -1;
|
||||
M[14] := -2 * zFar * zNear / (zFar - zNear);
|
||||
glLoadMatrixf(@M[0]);
|
||||
end;
|
||||
|
||||
procedure GLDraw;
|
||||
var
|
||||
ThreadInfo: TThreadInfo;
|
||||
begin
|
||||
GetThreadInfo($FFFFFFFF, ThreadInfo);
|
||||
if ThreadInfo.Client.Height <= 3 then Exit; // otherwise app crashes
|
||||
|
||||
kosglMakeCurrent(0, 0, ThreadInfo.Client.Width, ThreadInfo.Client.Height, CTX);
|
||||
glViewPort (0, 0, ThreadInfo.Client.Width, ThreadInfo.Client.Height);
|
||||
|
||||
glClearColor(0.11, 0.22, 0.66, 0);
|
||||
glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glLoadIdentity();
|
||||
|
||||
Perspective(45.0, ThreadInfo.Client.Width / ThreadInfo.Client.Height, 0.1, 100.0);
|
||||
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glLoadIdentity();
|
||||
|
||||
glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
glLoadIdentity();
|
||||
glTranslatef(0, 0, -5);
|
||||
|
||||
glRotatef(Angle, 0.25, 0.75, 0.75);
|
||||
|
||||
glBegin(GL_TRIANGLE_FAN);
|
||||
glColor3f(1, 0, 0); glVertex3f(0, 0.75, 0);
|
||||
glColor3f(1, 1, 0); glVertex3f(-0.75, -0.75, 0.75);
|
||||
glColor3f(1, 1, 1); glVertex3f(0.75, -0.75, 0.75);
|
||||
glColor3f(0, 1, 1); glVertex3f(0.75, -0.75, -0.75);
|
||||
glColor3f(0, 0, 1); glVertex3f(-0.75, -0.75, -0.75);
|
||||
glColor3f(0, 1, 0); glVertex3f(-0.75, -0.75, 0.75);
|
||||
glEnd();
|
||||
|
||||
Angle := Angle + Speed;
|
||||
if Angle > 360 then Angle := 0;
|
||||
|
||||
kosglSwapBuffers();
|
||||
end;
|
||||
|
||||
begin
|
||||
TinyGL_initialization;
|
||||
|
||||
with GetScreenSize do
|
||||
begin
|
||||
WndWidth := Width div 2;
|
||||
WndHeight := Height div 3 * 2;
|
||||
WndLeft := (Width - WndWidth) div 2;
|
||||
WndTop := (Height - WndHeight) div 2;
|
||||
end;
|
||||
|
||||
while True do
|
||||
case WaitEventByTime(1) of
|
||||
REDRAW_EVENT:
|
||||
begin
|
||||
BeginDraw;
|
||||
DrawWindow(WndLeft, WndTop, WndWidth, WndHeight, 'Pyramid TinyGL', $00FFFFFF,
|
||||
WS_SKINNED_SIZABLE + WS_TRANSPARENT_FILL + WS_CLIENT_COORDS + WS_CAPTION, CAPTION_MOVABLE);
|
||||
GLDraw;
|
||||
EndDraw;
|
||||
end;
|
||||
KEY_EVENT:
|
||||
GetKey;
|
||||
BUTTON_EVENT:
|
||||
if GetButton.ID = 1 then
|
||||
Exit;
|
||||
else
|
||||
GLDraw;
|
||||
end;
|
||||
|
||||
end.
|
||||
@@ -1,61 +0,0 @@
|
||||
program Select_Color_in_ColorDialog;
|
||||
|
||||
uses
|
||||
KolibriOS, ColorDlg;
|
||||
|
||||
var
|
||||
WndLeft, WndTop, WndWidth, WndHeight: Integer;
|
||||
TextColor: Integer = $00707070;
|
||||
ColorDialog: TColorDialog;
|
||||
|
||||
procedure On_Redraw;
|
||||
begin
|
||||
BeginDraw;
|
||||
DrawWindow(WndLeft, WndTop, WndWidth, WndHeight, 'Test ColorDialog, press key to select text color', $00FAFBFC,
|
||||
WS_SKINNED_SIZABLE + WS_CLIENT_COORDS + WS_CAPTION, CAPTION_MOVABLE);
|
||||
DrawText(2, 75, 'press key to select text color', TextColor, 0,
|
||||
DT_CP866_8X16 + DT_TRANSPARENT_FILL + DT_ZSTRING + DT_X2, 0);
|
||||
EndDraw;
|
||||
end;
|
||||
|
||||
begin
|
||||
ColorDlg_initialization;
|
||||
|
||||
with ColorDialog do
|
||||
begin
|
||||
Mode := CDM_PALETTE_TONE;
|
||||
DrawWindow := @On_Redraw;
|
||||
XSize := 510;
|
||||
YSize := 310;
|
||||
ColorType := CDCT_RGB;
|
||||
end;
|
||||
|
||||
with GetScreenSize do
|
||||
begin
|
||||
WndWidth := 600;
|
||||
WndHeight := Height div 3;
|
||||
WndLeft := (Width - WndWidth) div 2;
|
||||
WndTop := (Height - WndHeight) div 2;
|
||||
end;
|
||||
|
||||
ColorDialog.Init();
|
||||
|
||||
while True do
|
||||
case WaitEvent of
|
||||
REDRAW_EVENT:
|
||||
On_Redraw;
|
||||
KEY_EVENT:
|
||||
begin
|
||||
GetKey;
|
||||
ColorDialog.Start();
|
||||
with ColorDialog do
|
||||
if Status = CDS_OK then
|
||||
begin
|
||||
TextColor := Color;
|
||||
On_Redraw;
|
||||
end;
|
||||
end;
|
||||
BUTTON_EVENT:
|
||||
Exit;
|
||||
end;
|
||||
end.
|
||||
@@ -1,90 +0,0 @@
|
||||
program Select_File_in_OpenDialog;
|
||||
|
||||
uses
|
||||
KolibriOS, OpenDlg;
|
||||
|
||||
var
|
||||
WndLeft, WndTop, WndWidth, WndHeight: Integer;
|
||||
OpenDialog: TOpenDialog;
|
||||
TxtSelectResult: string = 'Yet not selected.';
|
||||
|
||||
procedure On_Redraw;
|
||||
begin
|
||||
BeginDraw;
|
||||
DrawWindow(WndLeft, WndTop, WndWidth, WndHeight, 'Select File in OpenDialog', $00FFFFFF,
|
||||
WS_SKINNED_FIXED + WS_CLIENT_COORDS + WS_CAPTION, CAPTION_MOVABLE);
|
||||
DrawText(2, 75, 'press key ENTER to select file', $00AF4F3F, 0,
|
||||
DT_CP866_8X16 + DT_TRANSPARENT_FILL + DT_ZSTRING, 0);
|
||||
DrawText(2, 90, 'press key SPACE to select dir', $003F4FAF, 0,
|
||||
DT_CP866_8X16 + DT_TRANSPARENT_FILL + DT_ZSTRING, 0);
|
||||
DrawText(15, 110, TxtSelectResult, $001F7F1F, 0,
|
||||
DT_CP866_8X16 + DT_TRANSPARENT_FILL, Length(TxtSelectResult));
|
||||
EndDraw;
|
||||
end;
|
||||
|
||||
procedure BrowseFile;
|
||||
begin
|
||||
with OpenDialog do
|
||||
begin
|
||||
Mode := ODM_OPEN;
|
||||
Start();
|
||||
if Status = ODS_OK then
|
||||
begin
|
||||
TxtSelectResult := 'File = "' + PString(OpenFilePath)^ + '"';
|
||||
On_Redraw;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure BrowseDir;
|
||||
begin
|
||||
with OpenDialog do
|
||||
begin
|
||||
Mode := ODM_DIR;
|
||||
Start();
|
||||
if Status = ODS_OK then
|
||||
begin
|
||||
TxtSelectResult := 'Dir = "' + PString(OpenFilePath)^ + '"';
|
||||
On_Redraw;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
begin
|
||||
OpenDlg_initialization;
|
||||
|
||||
with OpenDialog do
|
||||
begin
|
||||
DirDefaultPath := '/sys';
|
||||
DrawWindow := @On_Redraw;
|
||||
XSize := 400;
|
||||
YSize := 480;
|
||||
end;
|
||||
|
||||
with GetScreenSize do
|
||||
begin
|
||||
WndWidth := Width div 4;
|
||||
WndHeight := Height div 4;
|
||||
WndLeft := (Width - WndWidth) div 2;
|
||||
WndTop := (Height - WndHeight) div 2;
|
||||
end;
|
||||
|
||||
OpenDialog.Init();
|
||||
OpenDialog.SetFilter('txt,png,dat,ini,inf,sys,asm,htm');
|
||||
|
||||
while True do
|
||||
case WaitEvent of
|
||||
REDRAW_EVENT:
|
||||
On_Redraw;
|
||||
KEY_EVENT:
|
||||
case GetKey.Code of
|
||||
#13{ENTER}: BrowseFile;
|
||||
#32{SPACE}: BrowseDir;
|
||||
else
|
||||
// nothing to do
|
||||
end;
|
||||
BUTTON_EVENT:
|
||||
if GetButton.ID = 1 then
|
||||
Exit;
|
||||
end;
|
||||
end.
|
||||
@@ -1,70 +0,0 @@
|
||||
{ see original code here http://rosettacode.org/wiki/Sierpinski_triangle#Pascal }
|
||||
|
||||
{$APPTYPE CONSOLE}
|
||||
|
||||
program Sierpinski;
|
||||
|
||||
function ipow(b, n: Integer): Integer;
|
||||
var
|
||||
i: Integer;
|
||||
begin
|
||||
Result := 1;
|
||||
for i := 1 to n do
|
||||
Result := Result * b
|
||||
end;
|
||||
|
||||
function Truth(a: Char): Boolean;
|
||||
begin
|
||||
if a = '*' then
|
||||
Truth := True
|
||||
else
|
||||
Truth := False
|
||||
end;
|
||||
|
||||
function Rule_90(ev: string): string;
|
||||
var
|
||||
l, i: Integer;
|
||||
cp: string;
|
||||
s: array[0..1] of Boolean;
|
||||
begin
|
||||
l := Length(ev);
|
||||
cp := Copy(ev, 1, l);
|
||||
for i := 1 to l do
|
||||
begin
|
||||
if (i-1) < 1 then
|
||||
s[0] := False
|
||||
else
|
||||
s[0] := Truth(ev[i - 1]);
|
||||
if (i+1) > l then
|
||||
s[1] := False
|
||||
else
|
||||
s[1] := Truth(ev[i + 1]);
|
||||
if (s[0] and not s[1]) or (s[1] and not s[0]) then
|
||||
cp[i] := '*'
|
||||
else
|
||||
cp[i] := ' ';
|
||||
end;
|
||||
rule_90 := cp
|
||||
end;
|
||||
|
||||
procedure Triangle(N: Integer);
|
||||
var
|
||||
i, l : Integer;
|
||||
b : string;
|
||||
begin
|
||||
l := ipow(2, n + 1);
|
||||
b := ' ';
|
||||
for i := 1 to l do
|
||||
b := b + ' ';
|
||||
b[Round(l / 2)] := '*';
|
||||
WriteLn(b);
|
||||
for i := 1 to (Round(l / 2) - 1) do
|
||||
begin
|
||||
b := Rule_90(b);
|
||||
WriteLn(b)
|
||||
end
|
||||
end;
|
||||
|
||||
begin
|
||||
Triangle(4)
|
||||
end.
|
||||
@@ -1,79 +0,0 @@
|
||||
{ see original code here http://rosettacode.org/wiki/Spiral_matrix#Pascal }
|
||||
|
||||
{$APPTYPE CONSOLE}
|
||||
|
||||
program Spiralmat;
|
||||
|
||||
type
|
||||
TDir = (Left, Down, Right, Up);
|
||||
|
||||
TDXY = record
|
||||
DX, DY: LongInt;
|
||||
end;
|
||||
|
||||
TDeltaDir = array[TDir] of TDXY;
|
||||
|
||||
const
|
||||
Nextdir: array[TDir] of TDir = (Down, Right, Up, Left);
|
||||
cDir: TDeltaDir = ((dx: 1; dy: 0), (dx: 0; dy: 1), (dx: -1; dy: 0), (dx: 0; dy: -1));
|
||||
cMaxN = 32;
|
||||
|
||||
type
|
||||
TSpiral = array[0..cMaxN, 0..cMaxN] of LongInt;
|
||||
|
||||
function FillSpiral(n: LongInt): TSpiral;
|
||||
var
|
||||
b, i, k, dn, x, y : LongInt;
|
||||
dir: TDir;
|
||||
tmpSp: TSpiral;
|
||||
begin
|
||||
b := 0;
|
||||
x := 0;
|
||||
y := 0;
|
||||
//only for the first line
|
||||
k := -1;
|
||||
dn := n - 1;
|
||||
tmpSp[x, y] := b;
|
||||
dir := left;
|
||||
repeat
|
||||
i := 0;
|
||||
while i < dn do
|
||||
begin
|
||||
inc(b);
|
||||
tmpSp[x,y] := b;
|
||||
x := x + cDir[dir].dx;
|
||||
y := y + cDir[dir].dy;
|
||||
Inc(i);
|
||||
end;
|
||||
Dir := NextDir[dir];
|
||||
Inc(k);
|
||||
if k > 1 then
|
||||
begin
|
||||
k := 0;
|
||||
//shorten the line every second direction change
|
||||
dn := dn-1;
|
||||
if dn <= 0 then
|
||||
Break;
|
||||
end;
|
||||
until false;
|
||||
//the last
|
||||
tmpSp[x, y] := b + 1;
|
||||
FillSpiral := tmpSp;
|
||||
end;
|
||||
|
||||
var
|
||||
a: TSpiral;
|
||||
x, y, n: LongInt;
|
||||
begin
|
||||
for n := 1 to 5 do
|
||||
begin
|
||||
A := FillSpiral(n);
|
||||
for y := 0 to n - 1 do
|
||||
begin
|
||||
for x := 0 to n - 1 do
|
||||
Write(A[x, y]:4);
|
||||
WriteLn;
|
||||
end;
|
||||
WriteLn;
|
||||
end;
|
||||
end.
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 13 KiB |
@@ -1,63 +0,0 @@
|
||||
// Factorization demo
|
||||
|
||||
{$APPTYPE CONSOLE}
|
||||
|
||||
program Factor;
|
||||
|
||||
|
||||
|
||||
var
|
||||
LowBound, HighBound, Number, Dividend, Divisor: Integer;
|
||||
DivisorFound: Boolean;
|
||||
|
||||
|
||||
|
||||
begin
|
||||
WriteLn;
|
||||
WriteLn('Integer factorization demo');
|
||||
WriteLn;
|
||||
Write('From number: '); ReadLn(LowBound);
|
||||
Write('To number : '); ReadLn(HighBound);
|
||||
WriteLn;
|
||||
|
||||
if LowBound < 2 then
|
||||
begin
|
||||
WriteLn('Numbers should be greater than 1');
|
||||
ReadLn;
|
||||
Halt(1);
|
||||
end;
|
||||
|
||||
for Number := LowBound to HighBound do
|
||||
begin
|
||||
Write(Number, ' = ');
|
||||
|
||||
Dividend := Number;
|
||||
while Dividend > 1 do
|
||||
begin
|
||||
Divisor := 1;
|
||||
DivisorFound := FALSE;
|
||||
|
||||
while sqr(Divisor) <= Dividend do
|
||||
begin
|
||||
Inc(Divisor);
|
||||
if Dividend mod Divisor = 0 then
|
||||
begin
|
||||
DivisorFound := TRUE;
|
||||
Break;
|
||||
end;
|
||||
end;
|
||||
|
||||
if not DivisorFound then Divisor := Dividend; // Prime number
|
||||
|
||||
Write(Divisor, ' ');
|
||||
Dividend := Dividend div Divisor;
|
||||
end; // while
|
||||
|
||||
WriteLn;
|
||||
end; // for
|
||||
|
||||
WriteLn;
|
||||
WriteLn('Done.');
|
||||
|
||||
ReadLn;
|
||||
end.
|
||||
@@ -1,7 +0,0 @@
|
||||
{$APPTYPE CONSOLE}
|
||||
|
||||
program Hello;
|
||||
|
||||
begin
|
||||
WriteLn('Hello, World!');
|
||||
end.
|
||||
@@ -1,15 +0,0 @@
|
||||
@echo off
|
||||
|
||||
if exist bin rmdir /s /q bin
|
||||
mkdir bin
|
||||
|
||||
For /R %%i In (*.pas) Do (
|
||||
..\xdpk "%%i"
|
||||
)
|
||||
|
||||
:: Переносим все скомпилированные файлы .kex из подпапок в общую папку bin
|
||||
move /y *.kex bin\
|
||||
:: Если они сохраняются прямо рядом с исходниками в тех же папках, то лучше так:
|
||||
:: For /R %%i In (*.kex) Do move /y "%%i" bin\
|
||||
|
||||
pause
|
||||
@@ -1,440 +0,0 @@
|
||||
// Raytracer demo - demonstrates XD Pascal methods and interfaces
|
||||
|
||||
{$APPTYPE CONSOLE}
|
||||
|
||||
program Raytracer;
|
||||
|
||||
|
||||
type
|
||||
TVec = array [1..3] of Real;
|
||||
|
||||
|
||||
function add for u: TVec (var v: TVec): TVec;
|
||||
var i: Integer;
|
||||
begin
|
||||
for i := 1 to 3 do Result[i] := u[i] + v[i];
|
||||
end;
|
||||
|
||||
|
||||
function sub for u: TVec (var v: TVec): TVec;
|
||||
var i: Integer;
|
||||
begin
|
||||
for i := 1 to 3 do Result[i] := u[i] - v[i];
|
||||
end;
|
||||
|
||||
|
||||
function mul for v: TVec (a: Real): TVec;
|
||||
var i: Integer;
|
||||
begin
|
||||
for i := 1 to 3 do Result[i] := a * v[i];
|
||||
end;
|
||||
|
||||
|
||||
function dot for u: TVec (var v: TVec): Real;
|
||||
var i: Integer;
|
||||
begin
|
||||
Result := 0;
|
||||
for i := 1 to 3 do Result := Result + u[i] * v[i];
|
||||
end;
|
||||
|
||||
|
||||
function elementwise for u: TVec (var v: TVec): TVec;
|
||||
var i: Integer;
|
||||
begin
|
||||
for i := 1 to 3 do Result[i] := u[i] * v[i];
|
||||
end;
|
||||
|
||||
|
||||
function norm(var v: TVec): Real;
|
||||
begin
|
||||
Result := sqrt(v.dot(v));
|
||||
end;
|
||||
|
||||
|
||||
function normalize(var v: TVec): TVec;
|
||||
begin
|
||||
Result := v.mul(1.0 / norm(v));
|
||||
end;
|
||||
|
||||
|
||||
function rand: TVec;
|
||||
var i: Integer;
|
||||
begin
|
||||
for i := 1 to 3 do Result[i] := Random - 0.5;
|
||||
end;
|
||||
|
||||
|
||||
type
|
||||
TColor = TVec;
|
||||
|
||||
TRay = record
|
||||
Origin, Dir: TVec;
|
||||
end;
|
||||
|
||||
TGenericBody = record
|
||||
Center: TVec;
|
||||
Color: TColor;
|
||||
Diffuseness: Real;
|
||||
IsLamp: Boolean;
|
||||
end;
|
||||
|
||||
PGenericBody = ^TGenericBody;
|
||||
|
||||
|
||||
function LambertFactor for b: TGenericBody (Lambert: Real): Real;
|
||||
begin
|
||||
Result := 1.0 - (1.0 - Lambert) * b.Diffuseness;
|
||||
end;
|
||||
|
||||
|
||||
type
|
||||
TBox = record
|
||||
GenericBody: TGenericBody;
|
||||
HalfSize: TVec;
|
||||
end;
|
||||
|
||||
|
||||
function GetGenericBody for b: TBox: PGenericBody;
|
||||
begin
|
||||
Result := @b.GenericBody;
|
||||
end;
|
||||
|
||||
|
||||
function Intersect for b: TBox (var Ray: TRay; var Point, Normal: TVec): Boolean;
|
||||
|
||||
function IntersectFace(i, j, k: Integer): Boolean;
|
||||
|
||||
function Within(x, y, xmin, ymin, xmax, ymax: Real): Boolean;
|
||||
begin
|
||||
Result := (x > xmin) and (x < xmax) and (y > ymin) and (y < ymax);
|
||||
end;
|
||||
|
||||
var
|
||||
Side, Factor: Real;
|
||||
|
||||
begin // IntersectFace
|
||||
Result := FALSE;
|
||||
|
||||
if abs(Ray.Dir[k]) > 1e-9 then
|
||||
begin
|
||||
Side := 1.0;
|
||||
if Ray.Dir[k] > 0.0 then Side := -1.0;
|
||||
|
||||
Factor := (b.GenericBody.Center[k] + Side * b.HalfSize[k] - Ray.Origin[k]) / Ray.Dir[k];
|
||||
if Factor > 0.1 then
|
||||
begin
|
||||
Point := Ray.Origin.add(Ray.Dir.mul(Factor));
|
||||
|
||||
if Within(Point[i], Point[j],
|
||||
b.GenericBody.Center[i] - b.HalfSize[i], b.GenericBody.Center[j] - b.HalfSize[j],
|
||||
b.GenericBody.Center[i] + b.HalfSize[i], b.GenericBody.Center[j] + b.HalfSize[j])
|
||||
then
|
||||
begin
|
||||
Normal[i] := 0; Normal[j] := 0; Normal[k] := Side;
|
||||
Result := TRUE;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
begin // Intersect
|
||||
Result := IntersectFace(1, 2, 3) or IntersectFace(3, 1, 2) or IntersectFace(2, 3, 1);
|
||||
end;
|
||||
|
||||
|
||||
type
|
||||
TSphere = record
|
||||
GenericBody: TGenericBody;
|
||||
Radius: Real;
|
||||
end;
|
||||
|
||||
|
||||
function GetGenericBody for s: TSphere: PGenericBody;
|
||||
begin
|
||||
Result := @s.GenericBody;
|
||||
end;
|
||||
|
||||
|
||||
function Intersect for s: TSphere (var Ray: TRay; var Point, Normal: TVec): Boolean;
|
||||
var
|
||||
Displacement: TVec;
|
||||
Proj, Discr, Factor: Real;
|
||||
begin
|
||||
Displacement := s.GenericBody.Center.sub(Ray.Origin);
|
||||
Proj := Displacement.dot(Ray.Dir);
|
||||
Discr := sqr(s.Radius) + sqr(Proj) - Displacement.dot(Displacement);
|
||||
|
||||
if Discr > 0 then
|
||||
begin
|
||||
Factor := Proj - sqrt(Discr);
|
||||
if Factor > 0.1 then
|
||||
begin
|
||||
Point := Ray.Origin.add(Ray.Dir.mul(Factor));
|
||||
Normal := Point.sub(s.GenericBody.Center).mul(1.0 / s.Radius);
|
||||
Result := TRUE;
|
||||
Exit;
|
||||
end;
|
||||
end;
|
||||
|
||||
Result := FALSE;
|
||||
end;
|
||||
|
||||
|
||||
type
|
||||
IBody = interface
|
||||
GetGenericBody: function: PGenericBody;
|
||||
Intersect: function (var Ray: TRay; var Point, Normal: TVec): Boolean;
|
||||
end;
|
||||
|
||||
|
||||
const
|
||||
MAXBODIES = 10;
|
||||
|
||||
|
||||
type
|
||||
TScene = record
|
||||
AmbientColor: TColor;
|
||||
Body: array [1..MAXBODIES] of IBody;
|
||||
NumBodies: Integer;
|
||||
end;
|
||||
|
||||
|
||||
function Trace for sc: TScene (var Ray: TRay; Depth: Integer): TColor;
|
||||
var
|
||||
BestBody: PGenericBody;
|
||||
Point, Normal, BestPoint, BestNormal, SpecularDir, DiffuseDir: TVec;
|
||||
DiffuseRay: TRay;
|
||||
Dist, BestDist, Lambert: Real;
|
||||
BestIndex, i: Integer;
|
||||
|
||||
begin
|
||||
if Depth > 3 then
|
||||
begin
|
||||
Result := sc.AmbientColor;
|
||||
Exit;
|
||||
end;
|
||||
|
||||
// Find nearest intersection
|
||||
BestDist := 1e9;
|
||||
BestIndex := 0;
|
||||
|
||||
for i := 1 to sc.NumBodies do
|
||||
begin
|
||||
if sc.Body[i].Intersect(Ray, Point, Normal) then
|
||||
begin
|
||||
Dist := norm(Point.sub(Ray.Origin));
|
||||
if Dist < BestDist then
|
||||
begin
|
||||
BestDist := Dist;
|
||||
BestIndex := i;
|
||||
BestPoint := Point;
|
||||
BestNormal := Normal;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
// Reflect rays
|
||||
if BestIndex > 0 then
|
||||
begin
|
||||
BestBody := sc.Body[BestIndex].GetGenericBody();
|
||||
|
||||
if BestBody^.IsLamp then
|
||||
begin
|
||||
Result := BestBody^.Color;
|
||||
Exit;
|
||||
end;
|
||||
|
||||
SpecularDir := Ray.Dir.sub(BestNormal.mul(2.0 * (Ray.Dir.dot(BestNormal))));
|
||||
DiffuseDir := normalize(SpecularDir.add(rand.mul(2.0 * BestBody^.Diffuseness)));
|
||||
|
||||
Lambert := DiffuseDir.dot(BestNormal);
|
||||
if Lambert < 0 then
|
||||
begin
|
||||
DiffuseDir := DiffuseDir.sub(BestNormal.mul(2.0 * Lambert));
|
||||
Lambert := -Lambert;
|
||||
end;
|
||||
|
||||
DiffuseRay.Origin := BestPoint;
|
||||
DiffuseRay.Dir := DiffuseDir;
|
||||
|
||||
with BestBody^ do
|
||||
Result := sc.Trace(DiffuseRay, Depth + 1).mul(LambertFactor(Lambert)).elementwise(Color);
|
||||
|
||||
Exit;
|
||||
end;
|
||||
|
||||
Result := sc.AmbientColor;
|
||||
end;
|
||||
|
||||
|
||||
// Main program
|
||||
|
||||
const
|
||||
// Define scene
|
||||
Box1: TBox =
|
||||
(
|
||||
GenericBody:
|
||||
(
|
||||
Center: (500, -100, 1200);
|
||||
Color: (0.4, 0.7, 1.0);
|
||||
Diffuseness: 0.1;
|
||||
IsLamp: FALSE
|
||||
);
|
||||
HalfSize: (400 / 2, 600 / 2, 300 / 2)
|
||||
);
|
||||
|
||||
Box2: TBox =
|
||||
(
|
||||
GenericBody:
|
||||
(
|
||||
Center: (550, 210, 1100);
|
||||
Color: (0.9, 1.0, 0.6);
|
||||
Diffuseness: 0.3;
|
||||
IsLamp: FALSE
|
||||
);
|
||||
HalfSize: (1000 / 2, 20 / 2, 1000 / 2)
|
||||
);
|
||||
|
||||
Sphere1: TSphere =
|
||||
(
|
||||
GenericBody:
|
||||
(
|
||||
Center: (600, 0, 700);
|
||||
Color: (1.0, 0.4, 0.6);
|
||||
Diffuseness: 0.2;
|
||||
IsLamp: FALSE
|
||||
);
|
||||
Radius: 200
|
||||
);
|
||||
|
||||
Sphere2: TSphere =
|
||||
(
|
||||
GenericBody:
|
||||
(
|
||||
Center: (330, 150, 700);
|
||||
Color: (1.0, 1.0, 0.3);
|
||||
Diffuseness: 0.15;
|
||||
IsLamp: FALSE
|
||||
);
|
||||
Radius: 50
|
||||
);
|
||||
|
||||
// Define light
|
||||
Lamp1: TSphere =
|
||||
(
|
||||
GenericBody:
|
||||
(
|
||||
Center: (500, -1000, -700);
|
||||
Color: (1.0, 1.0, 1.0);
|
||||
Diffuseness: 1.0;
|
||||
IsLamp: TRUE
|
||||
);
|
||||
Radius: 800
|
||||
);
|
||||
|
||||
AmbientLightColor: TColor = (0.2, 0.2, 0.2);
|
||||
|
||||
|
||||
// Define eye
|
||||
Pos: TVec = (0, 0, 0);
|
||||
Azimuth = 30.0 * pi / 180.0;
|
||||
Width = 640;
|
||||
Height = 480;
|
||||
Focal = 500;
|
||||
Antialiasing = 1.0;
|
||||
|
||||
|
||||
// Output file
|
||||
FileName = 'scene.ppm';
|
||||
|
||||
|
||||
var
|
||||
Scene: TScene;
|
||||
Dir, RotDir, RandomDir: TVec;
|
||||
Color: TColor;
|
||||
Ray: TRay;
|
||||
sinAz, cosAz: Real;
|
||||
F: Text;
|
||||
Rays, i, j, r: Integer;
|
||||
StartTime, StopTime: LongInt;
|
||||
|
||||
Buf: array [0..Width * Height * 3 - 1] of Byte;
|
||||
BufPos: LongInt = 0;
|
||||
|
||||
|
||||
begin
|
||||
WriteLn('Raytracer demo');
|
||||
WriteLn;
|
||||
Write('Rays per pixel (recommended 1 to 100): '); ReadLn(Rays);
|
||||
WriteLn;
|
||||
|
||||
Randomize;
|
||||
|
||||
with Scene do
|
||||
begin
|
||||
AmbientColor := AmbientLightColor;
|
||||
Body[1] := Box1;
|
||||
Body[2] := Box2;
|
||||
Body[3] := Sphere1;
|
||||
Body[4] := Sphere2;
|
||||
Body[5] := Lamp1;
|
||||
NumBodies := 5;
|
||||
end;
|
||||
|
||||
sinAz := sin(Azimuth); cosAz := cos(Azimuth);
|
||||
|
||||
Assign(F, FileName);
|
||||
Rewrite(F);
|
||||
Write(F, 'P6 ');
|
||||
|
||||
Write(F, Width, ' ', Height, ' ');
|
||||
Write(F, 255, ' ');
|
||||
|
||||
StartTime := GetTickCount;
|
||||
|
||||
for i := 0 to Height - 1 do
|
||||
begin
|
||||
for j := 0 to Width - 1 do
|
||||
begin
|
||||
Color[1] := 0;
|
||||
Color[2] := 0;
|
||||
Color[3] := 0;
|
||||
|
||||
Dir[1] := j - Width / 2;
|
||||
Dir[2] := i - Height / 2;
|
||||
Dir[3] := Focal;
|
||||
|
||||
RotDir[1] := Dir[1] * cosAz + Dir[3] * sinAz;
|
||||
RotDir[2] := Dir[2];
|
||||
RotDir[3] := -Dir[1] * sinAz + Dir[3] * cosAz;
|
||||
|
||||
for r := 1 to Rays do
|
||||
begin
|
||||
RandomDir := RotDir.add(rand.mul(Antialiasing));
|
||||
Ray.Origin := Pos;
|
||||
Ray.Dir := normalize(RandomDir);
|
||||
Color := Color.add(Scene.Trace(Ray, 0));
|
||||
end;
|
||||
|
||||
Color := Color.mul(255.0 / Rays);
|
||||
|
||||
Buf[BufPos] := Round(Color[1]);
|
||||
Buf[BufPos + 1] := Round(Color[2]);
|
||||
Buf[BufPos + 2] := Round(Color[3]);
|
||||
BufPos := BufPos + 3;
|
||||
end;
|
||||
|
||||
WriteLn(i + 1, '/', Height);
|
||||
end;
|
||||
|
||||
BlockWrite(F, Buf, SizeOf(Buf));
|
||||
|
||||
StopTime := GetTickCount;
|
||||
|
||||
Close(F);
|
||||
|
||||
WriteLn;
|
||||
WriteLn('Rendering time: ', (StopTime - StartTime) / 1000 :5:1, ' s');
|
||||
WriteLn('Done. See ' + FileName);
|
||||
ReadLn;
|
||||
end.
|
||||
@@ -1,243 +0,0 @@
|
||||
// Sorting demo
|
||||
|
||||
{$APPTYPE CONSOLE}
|
||||
|
||||
program Sort;
|
||||
|
||||
|
||||
|
||||
type
|
||||
TValue = Integer;
|
||||
TCompareFunc = function(x, y: TValue): Boolean;
|
||||
|
||||
|
||||
|
||||
procedure Swap(var x, y: TValue);
|
||||
var
|
||||
buf: TValue;
|
||||
begin
|
||||
buf := x;
|
||||
x := y;
|
||||
y := buf;
|
||||
end;
|
||||
|
||||
|
||||
|
||||
procedure QuickSort(var data: array of TValue; len: Integer; Ordered: TCompareFunc);
|
||||
|
||||
|
||||
function Partition(var data: array of TValue; low, high: Integer; Ordered: TCompareFunc): Integer;
|
||||
var
|
||||
pivot: TValue;
|
||||
pivotIndex, i: Integer;
|
||||
begin
|
||||
pivot := data[high];
|
||||
pivotIndex := low;
|
||||
|
||||
for i := low to high - 1 do
|
||||
if not Ordered(data[i], pivot) then
|
||||
begin
|
||||
Swap(data[pivotIndex], data[i]);
|
||||
Inc(pivotIndex);
|
||||
end; // if
|
||||
|
||||
Swap(data[high], data[pivotIndex]);
|
||||
|
||||
Result := pivotIndex;
|
||||
end;
|
||||
|
||||
|
||||
procedure Sort(var data: array of TValue; low, high: Integer; Ordered: TCompareFunc);
|
||||
var
|
||||
pivotIndex: Integer;
|
||||
begin
|
||||
if high > low then
|
||||
begin
|
||||
pivotIndex := Partition(data, low, high, Ordered);
|
||||
|
||||
Sort(data, low, pivotIndex - 1, Ordered);
|
||||
Sort(data, pivotIndex + 1, high, Ordered);
|
||||
end; // if
|
||||
end;
|
||||
|
||||
|
||||
begin
|
||||
Sort(data, 0, len - 1, Ordered);
|
||||
end;
|
||||
|
||||
|
||||
|
||||
procedure BubbleSort(var data: array of TValue; len: Integer; Ordered: TCompareFunc);
|
||||
var
|
||||
changed: Boolean;
|
||||
i: Integer;
|
||||
begin
|
||||
repeat
|
||||
changed := FALSE;
|
||||
|
||||
for i := 0 to len - 2 do
|
||||
if not Ordered(data[i + 1], data[i]) then
|
||||
begin
|
||||
Swap(data[i + 1], data[i]);
|
||||
changed := TRUE;
|
||||
end;
|
||||
|
||||
until not changed;
|
||||
end;
|
||||
|
||||
|
||||
|
||||
procedure SelectionSort(var data: array of TValue; len: Integer; Ordered: TCompareFunc);
|
||||
var
|
||||
i, j, extrIndex: Integer;
|
||||
extr: TValue;
|
||||
begin
|
||||
for i := 0 to len - 1 do
|
||||
begin
|
||||
extr := data[i];
|
||||
extrIndex := i;
|
||||
|
||||
for j := i + 1 to len - 1 do
|
||||
if not Ordered(data[j], extr) then
|
||||
begin
|
||||
extr := data[j];
|
||||
extrIndex := j;
|
||||
end;
|
||||
|
||||
Swap(data[i], data[extrIndex]);
|
||||
end; // for
|
||||
end;
|
||||
|
||||
|
||||
|
||||
function Sorted(var data: array of TValue; len: Integer; Ordered: TCompareFunc): Boolean;
|
||||
var
|
||||
i: Integer;
|
||||
begin
|
||||
Result := TRUE;
|
||||
for i := 0 to len - 2 do
|
||||
if not Ordered(data[i + 1], data[i]) then
|
||||
begin
|
||||
Result := FALSE;
|
||||
Break;
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
|
||||
function OrderedAscending(y, x: TValue): Boolean;
|
||||
begin
|
||||
Result := y >= x;
|
||||
end;
|
||||
|
||||
|
||||
|
||||
function OrderedDescending(y, x: TValue): Boolean;
|
||||
begin
|
||||
Result := y <= x;
|
||||
end;
|
||||
|
||||
|
||||
|
||||
const
|
||||
DataLength = 600;
|
||||
|
||||
|
||||
|
||||
var
|
||||
RandomData: array [1..DataLength] of TValue;
|
||||
i: Integer;
|
||||
Ordered: TCompareFunc;
|
||||
Order, Method: Char;
|
||||
|
||||
|
||||
|
||||
begin
|
||||
WriteLn;
|
||||
WriteLn('Sorting demo');
|
||||
WriteLn;
|
||||
WriteLn('Initial array: ');
|
||||
WriteLn;
|
||||
|
||||
Randomize;
|
||||
|
||||
for i := 1 to DataLength do
|
||||
begin
|
||||
RandomData[i] := Round((Random - 0.5) * 1000000);
|
||||
Write(RandomData[i]: 8);
|
||||
if i mod 6 = 0 then WriteLn;
|
||||
end;
|
||||
|
||||
WriteLn;
|
||||
WriteLn;
|
||||
Write('Select order (A - ascending, D - descending): '); ReadLn(Order);
|
||||
WriteLn;
|
||||
|
||||
case Order of
|
||||
'A', 'a':
|
||||
begin
|
||||
WriteLn('Ascending order');
|
||||
Ordered := @OrderedAscending;
|
||||
end;
|
||||
'D', 'd':
|
||||
begin
|
||||
WriteLn('Descending order');
|
||||
Ordered := @OrderedDescending;
|
||||
end
|
||||
else
|
||||
WriteLn('Order is not selected.');
|
||||
Ordered := nil;
|
||||
ReadLn;
|
||||
Halt;
|
||||
end;
|
||||
|
||||
WriteLn;
|
||||
Write('Select method (Q - quick, B - bubble, S - selection): '); ReadLn(Method);
|
||||
WriteLn;
|
||||
|
||||
case Method of
|
||||
'Q', 'q':
|
||||
begin
|
||||
WriteLn('Quick sorting');
|
||||
QuickSort(RandomData, DataLength, Ordered);
|
||||
end;
|
||||
'B', 'b':
|
||||
begin
|
||||
WriteLn('Bubble sorting');
|
||||
BubbleSort(RandomData, DataLength, Ordered);
|
||||
end;
|
||||
'S', 's':
|
||||
begin
|
||||
WriteLn('Selection sorting');
|
||||
SelectionSort(RandomData, DataLength, Ordered);
|
||||
end
|
||||
else
|
||||
WriteLn('Sorting method is not selected.');
|
||||
ReadLn;
|
||||
Halt;
|
||||
end;
|
||||
|
||||
WriteLn;
|
||||
WriteLn('Sorted array: ');
|
||||
WriteLn;
|
||||
|
||||
for i := 1 to DataLength do
|
||||
begin
|
||||
Write(RandomData[i]: 8);
|
||||
if i mod 6 = 0 then WriteLn;
|
||||
end;
|
||||
WriteLn;
|
||||
|
||||
WriteLn('Sorted: ', Sorted(RandomData, DataLength, Ordered));
|
||||
WriteLn('Done.');
|
||||
|
||||
ReadLn;
|
||||
end.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,307 +0,0 @@
|
||||
program TorusDemo;
|
||||
|
||||
uses
|
||||
KolibriOS, TinyGL;
|
||||
|
||||
const
|
||||
MAX_VERTICES = 20000;
|
||||
MAX_FACES = 20000;
|
||||
|
||||
type
|
||||
TVertex = record
|
||||
x, y, z: Single;
|
||||
r, g, b: Byte;
|
||||
end;
|
||||
|
||||
TFace = record
|
||||
v1, v2, v3, v4: TVertex;
|
||||
avgZ: Single;
|
||||
colorR, colorG, colorB: Byte;
|
||||
end;
|
||||
|
||||
var
|
||||
WndLeft, WndTop, WndWidth, WndHeight: LongInt;
|
||||
CTX: TKOSGLContext;
|
||||
|
||||
MainRadius, BaseTubeRadius: Single;
|
||||
TorusSegments, TubeSegments, WaveCount: Integer;
|
||||
|
||||
ProjectedVertices: array[0..MAX_VERTICES - 1] of TVertex;
|
||||
Faces: array[0..MAX_FACES - 1] of TFace;
|
||||
TotalVerticesCount, TotalFacesCount: Integer;
|
||||
|
||||
AngleX: Single = 0.6;
|
||||
AngleY: Single = 0.5;
|
||||
TimeColor: Single = 0.0;
|
||||
TimeScale: Single = 0.0;
|
||||
|
||||
// яЁюЎхфєЁр яхЁёяхъЄштэющ ьрЄЁшЎ√
|
||||
procedure Perspective(fovY, Aspect, zNear, zFar: GLDouble);
|
||||
var
|
||||
fW, fH, fovYPI360: GLDouble;
|
||||
M: array[0..15] of GLFloat;
|
||||
begin
|
||||
FillChar(M, SizeOf(M), #0);
|
||||
fovYPI360 := fovY * PI / 360;
|
||||
fH := Sin(fovYPI360) * zNear / Cos(fovYPI360);
|
||||
fW := fH * Aspect;
|
||||
M[0] := zNear / fW;
|
||||
M[5] := zNear / fH;
|
||||
M[10] := -(zFar + zNear) / (zFar - zNear);
|
||||
M[11] := -1;
|
||||
M[14] := -2 * zFar * zNear / (zFar - zNear);
|
||||
glLoadMatrixf(@M[0]);
|
||||
end;
|
||||
|
||||
function Min(A, B: Extended): Extended;
|
||||
begin
|
||||
if A < B then Result := A else Result := B;
|
||||
end;
|
||||
|
||||
function Max(A, B: Extended): Extended;
|
||||
begin
|
||||
if A > B then Result := A else Result := B;
|
||||
end;
|
||||
|
||||
function Power(Base, Exponent: Extended): Extended;
|
||||
begin
|
||||
Result := Exp(Exponent * Ln(Base));
|
||||
end;
|
||||
|
||||
procedure ResizeTopology(W, H: Integer);
|
||||
begin
|
||||
MainRadius := H / 4.85;
|
||||
BaseTubeRadius := MainRadius / 2.45;
|
||||
|
||||
TorusSegments := Round(H / 10);
|
||||
TubeSegments := Round(H / 15);
|
||||
WaveCount := Round(H / 100);
|
||||
|
||||
if TorusSegments < 16 then TorusSegments := 16;
|
||||
if TubeSegments < 8 then TubeSegments := 8;
|
||||
if WaveCount < 3 then WaveCount := 3;
|
||||
|
||||
TotalVerticesCount := (TorusSegments + 1) * (TubeSegments + 1);
|
||||
TotalFacesCount := TorusSegments * TubeSegments;
|
||||
|
||||
// ╟р∙шЄр юЄ яхЁхяюыэхэш ёЄрЄшўхёъюую сєЇхЁр
|
||||
if TotalVerticesCount > MAX_VERTICES then TotalVerticesCount := MAX_VERTICES;
|
||||
if TotalFacesCount > MAX_FACES then TotalFacesCount := MAX_FACES;
|
||||
end;
|
||||
|
||||
procedure GLDraw;
|
||||
var
|
||||
ThreadInfo: TThreadInfo;
|
||||
I, J, Idx, Stride: Integer;
|
||||
U, V, Wave1, Wave2, CurrentTubeRadius, SpineWave: Single;
|
||||
CosU, SinU, CosV, SinV, CosX, SinX, CosY, SinY: Single;
|
||||
X, Y, Z, X1, Z1, Y2, Z2, Factor, Fov: Single;
|
||||
CamDist, CenterX, CenterY: Single;
|
||||
Idx1, Idx2, Idx3, Idx4: Integer;
|
||||
P1, P2, P3, P4: TVertex;
|
||||
AX, AY, AZ, BX, BY, BZ, NX, NY, NZ, Len: Single;
|
||||
RFinal, GFinal, BFinal: Single;
|
||||
ViewDot, Rim, CenterDarkness: Single;
|
||||
NormX, NormY, NormZ: Single;
|
||||
begin
|
||||
GetThreadInfo($FFFFFFFF, ThreadInfo);
|
||||
if not (ThreadInfo.Client.Height > 3) then Exit;
|
||||
|
||||
kosglMakeCurrent(0, 0, ThreadInfo.Client.Width, ThreadInfo.Client.Height, CTX);
|
||||
glViewPort(0, 0, ThreadInfo.Client.Width, ThreadInfo.Client.Height);
|
||||
|
||||
glClearColor(10/255, 10/255, 10/255, 0.0);
|
||||
glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
// ╤ўшЄрхь °руш ёхЄъш
|
||||
ResizeTopology(ThreadInfo.Client.Width, ThreadInfo.Client.Height);
|
||||
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glLoadIdentity();
|
||||
Perspective(45.0, ThreadInfo.Client.Width / ThreadInfo.Client.Height, 0.1, 100.0);
|
||||
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glLoadIdentity();
|
||||
|
||||
CamDist := 500.0;
|
||||
CenterX := ThreadInfo.Client.Width / 2.0;
|
||||
CenterY := ThreadInfo.Client.Height / 2.0;
|
||||
Fov := Min(ThreadInfo.Client.Width, ThreadInfo.Client.Height) * 1.1;
|
||||
|
||||
CosY := Cos(AngleY); SinY := Sin(AngleY);
|
||||
CosX := Cos(AngleX); SinX := Sin(AngleX);
|
||||
|
||||
// === ╪ру 1: ╠рЄхьрЄшўхёъшщ ЁрёўхЄ тюыэютюую ЄюЁр ===
|
||||
Idx := 0;
|
||||
for I := 0 to TorusSegments do
|
||||
begin
|
||||
U := (I / TorusSegments) * PI * 2.0;
|
||||
Wave1 := Sin(U * WaveCount + TimeScale) * (BaseTubeRadius * 0.44);
|
||||
Wave2 := Cos(U * (WaveCount * 2) - TimeScale * 1.5) * (BaseTubeRadius * 0.17);
|
||||
CurrentTubeRadius := BaseTubeRadius + Wave1 + Wave2;
|
||||
SpineWave := Sin(U * 3.0 - TimeScale * 1.2) * (MainRadius * 0.25);
|
||||
CosU := Cos(U); SinU := Sin(U);
|
||||
|
||||
for J := 0 to TubeSegments do
|
||||
begin
|
||||
if Idx >= MAX_VERTICES then Break;
|
||||
|
||||
V := (J / TubeSegments) * PI * 2.0;
|
||||
CosV := Cos(V); SinV := Sin(V);
|
||||
|
||||
X := (MainRadius + CurrentTubeRadius * CosV) * CosU;
|
||||
Y := CurrentTubeRadius * SinV + SpineWave;
|
||||
Z := (MainRadius + CurrentTubeRadius * CosV) * SinU;
|
||||
|
||||
X1 := X * CosY - Z * SinY;
|
||||
Z1 := X * SinY + Z * CosY;
|
||||
Y2 := Y * CosX - Z1 * SinX;
|
||||
Z2 := Y * SinX + Z1 * CosX;
|
||||
|
||||
Factor := Fov / (Z2 + CamDist);
|
||||
|
||||
ProjectedVertices[Idx].x := CenterX + X1 * Factor;
|
||||
ProjectedVertices[Idx].y := CenterY + Y2 * Factor;
|
||||
ProjectedVertices[Idx].z := Z2;
|
||||
|
||||
ProjectedVertices[Idx].r := Round((Sin(X * 0.015 + TimeColor) * 0.5 + 0.5) * 255.0);
|
||||
ProjectedVertices[Idx].g := Round((Sin(Y * 0.015 + TimeColor * 1.4) * 0.5 + 0.5) * 255.0);
|
||||
ProjectedVertices[Idx].b := Round((Cos(Z * 0.015 + TimeColor) * 0.5 + 0.5) * 255.0);
|
||||
|
||||
Inc(Idx);
|
||||
end;
|
||||
end;
|
||||
|
||||
// === ╪ру 2: ╤сюЁър ўхЄ√Ёхїєуюы№э√ї уЁрэхщ ш Rim Lighting ===
|
||||
Stride := TubeSegments + 1;
|
||||
Idx := 0;
|
||||
for I := 0 to TorusSegments - 1 do
|
||||
begin
|
||||
for J := 0 to TubeSegments - 1 do
|
||||
begin
|
||||
if Idx >= MAX_FACES then Break;
|
||||
|
||||
Idx1 := I * Stride + J;
|
||||
Idx2 := (I + 1) * Stride + J;
|
||||
Idx3 := (I + 1) * Stride + (J + 1);
|
||||
Idx4 := I * Stride + (J + 1);
|
||||
|
||||
if (Idx1 >= MAX_VERTICES) or (Idx2 >= MAX_VERTICES) or
|
||||
(Idx3 >= MAX_VERTICES) or (Idx4 >= MAX_VERTICES) then Continue;
|
||||
|
||||
P1 := ProjectedVertices[Idx1];
|
||||
P2 := ProjectedVertices[Idx2];
|
||||
P3 := ProjectedVertices[Idx3];
|
||||
P4 := ProjectedVertices[Idx4];
|
||||
|
||||
AX := P2.x - P1.x; AY := P2.y - P1.y; AZ := P2.z - P1.z;
|
||||
BX := P4.x - P1.x; BY := P4.y - P1.y; BZ := P4.z - P1.z;
|
||||
NX := AY * BZ - AZ * BY;
|
||||
NY := AZ * BX - ax * BZ;
|
||||
NZ := AX * BY - AY * BX;
|
||||
Len := Sqrt(NX * NX + NY * NY + NZ * NZ);
|
||||
|
||||
RFinal := P1.r; GFinal := P1.g; BFinal := P1.b;
|
||||
|
||||
if Len > 0.0 then
|
||||
begin
|
||||
NZ := NZ / Len;
|
||||
ViewDot := Abs(NZ);
|
||||
Rim := Power(1.0 - ViewDot, 3) * 1.5;
|
||||
CenterDarkness := Max(0.15, ViewDot * 0.5);
|
||||
|
||||
RFinal := (P1.r * CenterDarkness) + (P1.r * Rim);
|
||||
GFinal := (P1.g * CenterDarkness) + (P1.g * Rim);
|
||||
BFinal := (P1.b * CenterDarkness) + (P1.b * Rim);
|
||||
|
||||
if RFinal > 255.0 then RFinal := 255.0;
|
||||
if GFinal > 255.0 then GFinal := 255.0;
|
||||
if BFinal > 255.0 then BFinal := 255.0;
|
||||
end;
|
||||
|
||||
Faces[Idx].v1 := P1;
|
||||
Faces[Idx].v2 := P2;
|
||||
Faces[Idx].v3 := P3;
|
||||
Faces[Idx].v4 := P4;
|
||||
Faces[Idx].avgZ := (P1.z + P2.z + P3.z + P4.z) * 0.25;
|
||||
Faces[Idx].colorR := Round(RFinal);
|
||||
Faces[Idx].colorG := Round(GFinal);
|
||||
Faces[Idx].colorB := Round(BFinal);
|
||||
|
||||
Inc(Idx);
|
||||
end;
|
||||
end;
|
||||
|
||||
// ╬ЄЁшёютър т ёЄрэфрЁЄэюь яхЁёяхъЄштэюь 3D-яЁюёЄЁрэёЄтх
|
||||
// ╤фтшурхь ёЎхэє эрчрф яю юёш Z, ўЄюс√ ухюьхЄЁш яюыэюёЄ№■ тю°ыр т яшЁрьшфє Frustum
|
||||
glTranslatef(0.0, 0.0, -4.7);
|
||||
|
||||
// === ╪ру 4: ┬шчєрышчрЎш яюышуюэют ёЁхфёЄтрьш TinyGL ===
|
||||
for I := 0 to TotalFacesCount - 1 do
|
||||
begin
|
||||
glBegin(GL_QUADS);
|
||||
glColor3f(Faces[I].colorR / 255.0, Faces[I].colorG / 255.0, Faces[I].colorB / 255.0);
|
||||
|
||||
// яхЁхтюфшь яшъёхыш т фшрярчюэ (-1.0..1.0)
|
||||
// ┬ glVertex3f яхЁхфрхЄё уыєсшэр NormZ
|
||||
NormX := (Faces[I].v1.x / ThreadInfo.Client.Width) * 2.0 - 1.0;
|
||||
NormY := 1.0 - (Faces[I].v1.y / ThreadInfo.Client.Height) * 2.0;
|
||||
NormZ := -((Faces[I].v1.z + 250.0) / 500.0); // ╠рё°ЄрсшЁєхь Z т ърэюэшўхёъшщ фшрярчюэ тшфшьюёЄш
|
||||
glVertex3f(NormX * 1.95, NormY * 1.45, NormZ);
|
||||
|
||||
NormX := (Faces[I].v2.x / ThreadInfo.Client.Width) * 2.0 - 1.0;
|
||||
NormY := 1.0 - (Faces[I].v2.y / ThreadInfo.Client.Height) * 2.0;
|
||||
NormZ := -((Faces[I].v2.z + 250.0) / 500.0);
|
||||
glVertex3f(NormX * 1.95, NormY * 1.45, NormZ);
|
||||
|
||||
NormX := (Faces[I].v3.x / ThreadInfo.Client.Width) * 2.0 - 1.0;
|
||||
NormY := 1.0 - (Faces[I].v3.y / ThreadInfo.Client.Height) * 2.0;
|
||||
NormZ := -((Faces[I].v3.z + 250.0) / 500.0);
|
||||
glVertex3f(NormX * 1.95, NormY * 1.45, NormZ);
|
||||
|
||||
NormX := (Faces[I].v4.x / ThreadInfo.Client.Width) * 2.0 - 1.0;
|
||||
NormY := 1.0 - (Faces[I].v4.y / ThreadInfo.Client.Height) * 2.0;
|
||||
NormZ := -((Faces[I].v4.z + 250.0) / 500.0);
|
||||
glVertex3f(NormX * 1.95, NormY * 1.45, NormZ);
|
||||
glEnd();
|
||||
end;
|
||||
|
||||
kosglSwapBuffers();
|
||||
|
||||
// === ╪ру 5: ╚эъЁхьхэЄ °руют рэшьрЎшш ш фшэрьшўхёъшї Їрчют√ї ёфтшуют ===
|
||||
AngleX := AngleX + 0.01;
|
||||
AngleY := AngleY + 0.02;
|
||||
TimeColor := TimeColor + 0.02;
|
||||
TimeScale := TimeScale + 0.1;
|
||||
end;
|
||||
|
||||
begin
|
||||
TinyGL_initialization;
|
||||
|
||||
with GetScreenSize do
|
||||
begin
|
||||
WndWidth := Width div 3 * 2;
|
||||
WndHeight := Height div 3 * 2;
|
||||
WndLeft := (Width - WndWidth) div 2;
|
||||
WndTop := (Height - WndHeight) div 2;
|
||||
end;
|
||||
|
||||
while True do
|
||||
case WaitEventByTime(1) of
|
||||
REDRAW_EVENT:
|
||||
begin
|
||||
BeginDraw;
|
||||
DrawWindow(WndLeft, WndTop, WndWidth, WndHeight, 'TinyGL Torus Demo', $00FFFFFF,
|
||||
WS_SKINNED_SIZABLE + WS_CLIENT_COORDS + WS_CAPTION, CAPTION_MOVABLE);
|
||||
GLDraw;
|
||||
EndDraw;
|
||||
end;
|
||||
KEY_EVENT:
|
||||
GetKey;
|
||||
BUTTON_EVENT:
|
||||
if GetButton.ID = 1 then
|
||||
ExitThread;
|
||||
else
|
||||
GLDraw;
|
||||
end;
|
||||
end.
|
||||
@@ -1,368 +0,0 @@
|
||||
program CircleParticlesTinyGL;
|
||||
|
||||
uses
|
||||
KolibriOS, TinyGL;
|
||||
|
||||
const
|
||||
// ╠ръёшьры№эюх ъюышўхёЄтю ўрёЄшЎ
|
||||
MAX_PARTICLES = 3000;
|
||||
|
||||
// ╩юышўхёЄтю эют√ї ўрёЄшЎ чр ърфЁ
|
||||
SPAWN_PER_FRAME = 18;
|
||||
|
||||
// ╨рчьхЁ ярышЄЁ√
|
||||
PALETTE_SIZE = 64;
|
||||
|
||||
// ╩юышўхёЄтю ёхуьхэЄют ъЁєур
|
||||
CIRCLE_SEGMENTS = 12;
|
||||
|
||||
// ╙уюы юсчюЁр яхЁёяхъЄшт√
|
||||
FIELD_OF_VIEW = 45.0;
|
||||
|
||||
type
|
||||
// ╫рёЄшЎр
|
||||
TParticle = record
|
||||
Life: LongInt;
|
||||
X, Y: GLFloat;
|
||||
VX, VY: GLFloat;
|
||||
Radius: GLFloat;
|
||||
end;
|
||||
|
||||
// ╓тхЄ ярышЄЁ√
|
||||
TPaletteColor = record
|
||||
R, G, B: GLFloat;
|
||||
end;
|
||||
|
||||
var
|
||||
// ╩юэЄхъёЄ TinyGL
|
||||
CTX: TKOSGLContext;
|
||||
|
||||
// ╧єы ўрёЄшЎ
|
||||
Particles: array[0..MAX_PARTICLES - 1] of TParticle;
|
||||
|
||||
// ╨рфєцэр ярышЄЁр
|
||||
RainbowPalette: array[0..PALETTE_SIZE - 1] of TPaletteColor;
|
||||
|
||||
// ╩єЁёюЁ яюшёър ётюсюфэющ ўрёЄшЎ√
|
||||
PoolCursor: LongInt = 0;
|
||||
|
||||
// ╤ў╕Єўшъ ърфЁют
|
||||
FrameCounter: LongInt = 0;
|
||||
|
||||
// ╨рчьхЁ√ ш яюыюцхэшх юъэр
|
||||
WndLeft, WndTop, WndWidth, WndHeight: LongInt;
|
||||
|
||||
// ═рёЄЁющър яхЁёяхъЄшт√ ърьхЁ√
|
||||
procedure Perspective(fovY, Aspect, zNear, zFar: GLDouble);
|
||||
var
|
||||
fW, fH, fovYPI360: GLDouble;
|
||||
M: array[0..15] of GLFloat;
|
||||
begin
|
||||
FillChar(M, SizeOf(M), #0);
|
||||
fovYPI360 := fovY * PI / 360;
|
||||
fH := Sin(fovYPI360) * zNear / Cos(fovYPI360);
|
||||
fW := fH * Aspect;
|
||||
M[0] := zNear / fW;
|
||||
M[5] := zNear / fH;
|
||||
M[10] := -(zFar + zNear) / (zFar - zNear);
|
||||
M[11] := -1;
|
||||
M[14] := -2 * zFar * zNear / (zFar - zNear);
|
||||
glLoadMatrixf(@M[0]);
|
||||
end;
|
||||
|
||||
// ╤ыєўрщэюх Float ўшёыю
|
||||
function RandomFloat(MinValue, MaxValue: GLFloat): GLFloat;
|
||||
begin
|
||||
RandomFloat :=
|
||||
MinValue +
|
||||
Random * (MaxValue - MinValue);
|
||||
end;
|
||||
|
||||
// HSV -> RGB
|
||||
procedure HSVtoRGB(H, S, V: GLFloat; var R, G, B: GLFloat);
|
||||
var
|
||||
I: LongInt;
|
||||
F, P, Q, T: GLFloat;
|
||||
begin
|
||||
H := H * 6.0;
|
||||
I := Trunc(H);
|
||||
F := H - I;
|
||||
P := V * (1.0 - S);
|
||||
Q := V * (1.0 - S * F);
|
||||
T := V * (1.0 - S * (1.0 - F));
|
||||
case I mod 6 of
|
||||
0: begin R := V; G := T; B := P; end;
|
||||
1: begin R := Q; G := V; B := P; end;
|
||||
2: begin R := P; G := V; B := T; end;
|
||||
3: begin R := P; G := Q; B := V; end;
|
||||
4: begin R := T; G := P; B := V; end;
|
||||
else
|
||||
begin R := V; G := P; B := Q; end;
|
||||
end;
|
||||
end;
|
||||
|
||||
// ╨рфєцэр ярышЄЁр
|
||||
procedure BuildRainbowPalette;
|
||||
var
|
||||
I: LongInt;
|
||||
H: GLFloat;
|
||||
begin
|
||||
for I := 0 to PALETTE_SIZE - 1 do
|
||||
begin
|
||||
H := 1 - I / (PALETTE_SIZE - 1);
|
||||
HSVtoRGB(
|
||||
H,
|
||||
1.0,
|
||||
1.0,
|
||||
RainbowPalette[I].R,
|
||||
RainbowPalette[I].G,
|
||||
RainbowPalette[I].B
|
||||
);
|
||||
end;
|
||||
end;
|
||||
|
||||
// ╨шёютрэшх ъЁєуыющ ўрёЄшЎ√
|
||||
procedure DrawParticleCircle(X, Y, Radius: GLFloat);
|
||||
var
|
||||
I: LongInt;
|
||||
Angle, PX, PY: GLFloat;
|
||||
begin
|
||||
glBegin(GL_TRIANGLE_FAN);
|
||||
|
||||
// ╓хэЄЁ ъЁєур
|
||||
glVertex3f(X, Y, 0.0);
|
||||
|
||||
// ╬ъЁєцэюёЄ№
|
||||
for I := 0 to CIRCLE_SEGMENTS do
|
||||
begin
|
||||
Angle := (PI * 2.0 * I) / CIRCLE_SEGMENTS;
|
||||
|
||||
PX := X + Cos(Angle) * Radius;
|
||||
PY := Y + Sin(Angle) * Radius;
|
||||
|
||||
glVertex3f(PX, PY, 0.0);
|
||||
end;
|
||||
|
||||
glEnd();
|
||||
end;
|
||||
|
||||
// ╤ючфрэшх ўрёЄшЎ√
|
||||
procedure SpawnParticle(EmitX, EmitY: GLFloat);
|
||||
var
|
||||
Attempts: LongInt;
|
||||
P: ^TParticle;
|
||||
Angle,
|
||||
Speed: GLFloat;
|
||||
begin
|
||||
Attempts := MAX_PARTICLES;
|
||||
|
||||
while Attempts > 0 do
|
||||
begin
|
||||
P := @Particles[PoolCursor];
|
||||
|
||||
PoolCursor :=
|
||||
(PoolCursor + 1) mod MAX_PARTICLES;
|
||||
|
||||
if P^.Life <= 0 then
|
||||
begin
|
||||
Angle := RandomFloat(0.0, PI * 2.0);
|
||||
Speed := RandomFloat(5.0, 13.0);
|
||||
|
||||
P^.X := EmitX;
|
||||
P^.Y := EmitY;
|
||||
|
||||
P^.VX := Cos(Angle) * Speed;
|
||||
P^.VY := Sin(Angle) * Speed - 7.0;
|
||||
|
||||
P^.Life := Round(40 + Random * 24);
|
||||
|
||||
P^.Radius := 1 + Random * 3;
|
||||
|
||||
Exit;
|
||||
end;
|
||||
|
||||
Dec(Attempts);
|
||||
end;
|
||||
end;
|
||||
|
||||
// ╬ёэютэющ ЁхэфхЁ
|
||||
procedure GLDraw;
|
||||
var
|
||||
ThreadInfo: TThreadInfo;
|
||||
Width,
|
||||
Height: LongInt;
|
||||
CameraZ, EmitX,
|
||||
EmitY: GLFloat;
|
||||
I: LongInt;
|
||||
P: ^TParticle;
|
||||
begin
|
||||
GetThreadInfo($FFFFFFFF, ThreadInfo);
|
||||
|
||||
Width := ThreadInfo.Client.Width;
|
||||
Height := ThreadInfo.Client.Height;
|
||||
|
||||
if Height <= 3 then Exit;
|
||||
|
||||
kosglMakeCurrent(0, 0, Width, Height, CTX);
|
||||
glViewPort( 0, 0, Width, Height);
|
||||
|
||||
// ╧хЁт√щ ърфЁ яюыэюёЄ№■ юўш∙рхЄ ¤ъЁрэ
|
||||
if FrameCounter = 0 then
|
||||
begin
|
||||
glClearColor(0.0, 0.0, 0.0, 1.0);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
end;
|
||||
|
||||
// ═рёЄЁющър яхЁёяхъЄшт√
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glLoadIdentity();
|
||||
Perspective(
|
||||
FIELD_OF_VIEW,
|
||||
Width / Height,
|
||||
0.1,
|
||||
5000.0
|
||||
);
|
||||
|
||||
// ─шэрьшўхёър ърьхЁр
|
||||
// ╨рчьхЁ ёЎхэ√ ёЄрсшыхэ яЁш ы■сюь ЁрчьхЁх юъэр
|
||||
CameraZ :=
|
||||
Height /
|
||||
(Sin(FIELD_OF_VIEW * PI / 360.0) /
|
||||
Cos(FIELD_OF_VIEW * PI / 360.0));
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glLoadIdentity();
|
||||
glTranslatef(
|
||||
-Width * 0.5,
|
||||
-Height * 0.5,
|
||||
-CameraZ * 0.5
|
||||
);
|
||||
|
||||
// ╧юыюцхэшх ¤ьшЄЄхЁр
|
||||
// ╬ЄёЄєя√ ёЄрсшы№э√ яЁш ы■сюь ЁрчьхЁх юъэр
|
||||
EmitX :=
|
||||
(Width * 0.5) +
|
||||
Sin(FrameCounter * 0.03) *
|
||||
(Width * 0.46);
|
||||
|
||||
EmitY :=
|
||||
(Height * 0.5) +
|
||||
Cos(FrameCounter * 0.02) *
|
||||
(Height * 0.44);
|
||||
|
||||
// ╤ючфрэшх эют√ї ўрёЄшЎ
|
||||
for I := 0 to SPAWN_PER_FRAME - 1 do
|
||||
SpawnParticle(EmitX, EmitY);
|
||||
|
||||
// ╬сэютыхэшх ўрёЄшЎ
|
||||
for I := 0 to MAX_PARTICLES - 1 do
|
||||
begin
|
||||
P := @Particles[I];
|
||||
|
||||
if P^.Life <= 0 then
|
||||
Continue;
|
||||
|
||||
// ─тшцхэшх
|
||||
P^.X := P^.X + P^.VX;
|
||||
P^.Y := P^.Y + P^.VY;
|
||||
|
||||
// ├ЁртшЄрЎш
|
||||
P^.VY := P^.VY + 0.18;
|
||||
|
||||
// ╬Єёъюъ юЄ ёЄхэюъ
|
||||
if P^.X > Width - P^.Radius then
|
||||
begin
|
||||
P^.X := Width - P^.Radius;
|
||||
P^.VX := P^.VX * (-0.80);
|
||||
end;
|
||||
|
||||
if P^.X < P^.Radius then
|
||||
begin
|
||||
P^.X := P^.Radius;
|
||||
P^.VX := P^.VX * (-0.80);
|
||||
end;
|
||||
|
||||
// ╬Єёъюъ юЄ яюЄюыър ш яюыр
|
||||
if P^.Y > Height - P^.Radius then
|
||||
begin
|
||||
P^.Y := Height - P^.Radius;
|
||||
P^.VY := P^.VY * (-0.70);
|
||||
P^.VX := P^.VX * 0.94;
|
||||
end;
|
||||
|
||||
if P^.Y < P^.Radius then
|
||||
begin
|
||||
P^.Y := P^.Radius;
|
||||
P^.VY := P^.VY * (-0.70);
|
||||
P^.VX := P^.VX * 0.94;
|
||||
end;
|
||||
|
||||
// ╙ьхэ№°хэшх цшчэш
|
||||
Dec(P^.Life);
|
||||
|
||||
if P^.Life > 0 then
|
||||
begin
|
||||
glColor3f(
|
||||
RainbowPalette[P^.Life].R,
|
||||
RainbowPalette[P^.Life].G,
|
||||
RainbowPalette[P^.Life].B
|
||||
);
|
||||
|
||||
DrawParticleCircle(
|
||||
P^.X,
|
||||
P^.Y,
|
||||
P^.Radius
|
||||
);
|
||||
end;
|
||||
end;
|
||||
|
||||
// ┬√тюф ърфЁр
|
||||
kosglSwapBuffers();
|
||||
|
||||
Inc(FrameCounter);
|
||||
end;
|
||||
|
||||
begin
|
||||
TinyGL_initialization;
|
||||
|
||||
Randomize;
|
||||
BuildRainbowPalette;
|
||||
|
||||
with GetScreenSize do
|
||||
begin
|
||||
WndWidth := Width div 2;
|
||||
WndHeight := Height div 2;
|
||||
WndLeft := (Width - WndWidth) div 2;
|
||||
WndTop := (Height - WndHeight) div 2;
|
||||
end;
|
||||
|
||||
while True do
|
||||
begin
|
||||
case WaitEventByTime(1) of
|
||||
REDRAW_EVENT:
|
||||
begin
|
||||
BeginDraw;
|
||||
DrawWindow(
|
||||
WndLeft,
|
||||
WndTop,
|
||||
WndWidth,
|
||||
WndHeight,
|
||||
'Circle Particles TinyGL',
|
||||
$00000000,
|
||||
WS_SKINNED_SIZABLE +
|
||||
WS_CLIENT_COORDS +
|
||||
WS_CAPTION,
|
||||
CAPTION_MOVABLE
|
||||
);
|
||||
GLDraw;
|
||||
EndDraw;
|
||||
end;
|
||||
KEY_EVENT:
|
||||
GetKey;
|
||||
BUTTON_EVENT:
|
||||
if GetButton.ID = 1 then
|
||||
ExitThread;
|
||||
else
|
||||
GLDraw;
|
||||
end;
|
||||
end;
|
||||
end.
|
||||
@@ -1,169 +0,0 @@
|
||||
program DNAHelix3D;
|
||||
|
||||
uses
|
||||
KolibriOS, TinyGL;
|
||||
|
||||
const
|
||||
MAX_ELEMENTS = 40; { ╩юышўхёЄтю ёЄєяхэхщ т Ўхяюўъх ─═╩ }
|
||||
RADIUS = 1.1; { ╨рфшєё чръЁєўштрэш ёяшЁрыш }
|
||||
STEP_HEIGHT = 0.12; { ╨рёёЄю эшх ьхцфє ёЄєяхэ ьш яю тхЁЄшърыш }
|
||||
|
||||
type
|
||||
TBaseNode = record
|
||||
X1, Y1, Z1: GLFloat;
|
||||
X2, Y2, Z2: GLFloat;
|
||||
R, G, B: GLFloat;
|
||||
end;
|
||||
|
||||
var
|
||||
Nodes: array[1..MAX_ELEMENTS] of TBaseNode;
|
||||
Rotation: GLFloat = 0;
|
||||
Speed: GLFloat = 0.5;
|
||||
ZTr: GLFloat = -7.5;
|
||||
TimeVal: GLFloat = 0;
|
||||
CTX: TKOSGLContext;
|
||||
|
||||
WndLeft, WndTop, WndWidth, WndHeight: LongInt;
|
||||
|
||||
// ═рёЄЁющър яхЁёяхъЄшт√ ърьхЁ√
|
||||
procedure Perspective(fovY, Aspect, zNear, zFar: GLDouble);
|
||||
var
|
||||
fW, fH, fovYPI360: GLDouble;
|
||||
M: array[0..15] of GLFloat;
|
||||
begin
|
||||
FillChar(M, SizeOf(M), #0);
|
||||
fovYPI360 := fovY * PI / 360;
|
||||
fH := Sin(fovYPI360) * zNear / Cos(fovYPI360);
|
||||
fW := fH * Aspect;
|
||||
M[0] := zNear / fW;
|
||||
M[5] := zNear / fH;
|
||||
M[10] := -(zFar + zNear) / (zFar - zNear);
|
||||
M[11] := -1;
|
||||
M[14] := -2 * zFar * zNear / (zFar - zNear);
|
||||
glLoadMatrixf(@M[0]);
|
||||
end;
|
||||
|
||||
{ ╠рЄхьрЄшўхёъшщ ЁрёўхЄ тюыэютюую ёъЁєўштрэш ш фхЇюЁьрЎшш ─═╩ }
|
||||
procedure UpdateDNAPhysics;
|
||||
var
|
||||
I: Integer;
|
||||
Angle, VertPos, Wave: GLFloat;
|
||||
begin
|
||||
for I := 1 to MAX_ELEMENTS do
|
||||
begin
|
||||
{ ┴рчют√щ єуюы чръЁєўштрэш + фшэрьшўхёър тюыэр тЁхьхэш }
|
||||
Angle := (I * 0.4) + Sin(TimeVal + I * 0.15) * 0.25;
|
||||
VertPos := (I - (MAX_ELEMENTS div 2)) * STEP_HEIGHT;
|
||||
|
||||
{ ╥хяыютющ тюыэютющ °єь }
|
||||
Wave := Cos(TimeVal * 2.0 + I * 0.1) * 0.08;
|
||||
|
||||
{ ═шЄ№ └ ёяшЁрыш }
|
||||
Nodes[I].X1 := Cos(Angle) * (RADIUS + Wave);
|
||||
Nodes[I].Y1 := VertPos;
|
||||
Nodes[I].Z1 := Sin(Angle) * (RADIUS + Wave);
|
||||
|
||||
{ ═шЄ№ ┴ ёяшЁрыш (яЁюЄштюЇрчр 180 уЁрфєёют / PI) }
|
||||
Nodes[I].X2 := Cos(Angle + 3.14159) * (RADIUS + Wave);
|
||||
Nodes[I].Y2 := VertPos;
|
||||
Nodes[I].Z2 := Sin(Angle + 3.14159) * (RADIUS + Wave);
|
||||
|
||||
{ ╓тхЄютюх ъюфшЁютрэшх эєъыхюЄшфют т чртшёшьюёЄш юЄ т√ёюЄ√ }
|
||||
Nodes[I].R := 0.4 + Sin(I * 0.2) * 0.4;
|
||||
Nodes[I].G := 0.2 + Cos(I * 0.1) * 0.4;
|
||||
Nodes[I].B := 0.8 - Sin(I * 0.05) * 0.2;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure GLDraw;
|
||||
var
|
||||
ThreadInfo: TThreadInfo;
|
||||
I: Integer;
|
||||
S: GLFloat;
|
||||
begin
|
||||
GetThreadInfo($FFFFFFFF, ThreadInfo);
|
||||
if ThreadInfo.Client.Height <= 3 then Exit;
|
||||
|
||||
kosglMakeCurrent(0, 0, ThreadInfo.Client.Width, ThreadInfo.Client.Height, CTX);
|
||||
glViewPort(0, 0, ThreadInfo.Client.Width, ThreadInfo.Client.Height);
|
||||
|
||||
glClearColor(0.15, 0.15, 0.3, 0.0); { ├ыєсюъшщ сшю-ъшсхЁэхЄшўхёъшщ Їюэ }
|
||||
glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glLoadIdentity();
|
||||
Perspective(45.0, ThreadInfo.Client.Width / ThreadInfo.Client.Height, 0.1, 100.0);
|
||||
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glLoadIdentity();
|
||||
|
||||
glTranslatef(0.0, 0.0, ZTr);
|
||||
glRotatef(Rotation, 0.3, 1.0, 0.1); { ╧ыртэ√щ юсыхЄ ърьхЁ√ }
|
||||
|
||||
S := 0.06; { ╥юы∙шэр єчыют }
|
||||
|
||||
for I := 1 to MAX_ELEMENTS do
|
||||
begin
|
||||
{ 1. ╨шёєхь яхЁхь√ўъш ьхцфє эшЄ ьш ─═╩ }
|
||||
glBegin(GL_QUADS);
|
||||
glColor3f(Nodes[I].R * 0.6, Nodes[I].G * 0.6, Nodes[I].B * 0.6);
|
||||
glVertex3f(Nodes[I].X1, Nodes[I].Y1 - 0.02, Nodes[I].Z1);
|
||||
glVertex3f(Nodes[I].X2, Nodes[I].Y2 - 0.02, Nodes[I].Z2);
|
||||
glVertex3f(Nodes[I].X2, Nodes[I].Y2 + 0.02, Nodes[I].Z2);
|
||||
glVertex3f(Nodes[I].X1, Nodes[I].Y1 + 0.02, Nodes[I].Z1);
|
||||
glEnd();
|
||||
|
||||
{ 2. ╨шёєхь ёЇхЁє-ъєсшъ эшЄш └ }
|
||||
glBegin(GL_QUADS);
|
||||
glColor3f(Nodes[I].R, Nodes[I].G, Nodes[I].B);
|
||||
glVertex3f(Nodes[I].X1 - S, Nodes[I].Y1 - S, Nodes[I].Z1 + S);
|
||||
glVertex3f(Nodes[I].X1 + S, Nodes[I].Y1 - S, Nodes[I].Z1 + S);
|
||||
glVertex3f(Nodes[I].X1 + S, Nodes[I].Y1 + S, Nodes[I].Z1 + S);
|
||||
glVertex3f(Nodes[I].X1 - S, Nodes[I].Y1 + S, Nodes[I].Z1 + S);
|
||||
glEnd();
|
||||
|
||||
{ 3. ╨шёєхь ёЇхЁє-ъєсшъ эшЄш ┴ }
|
||||
glBegin(GL_QUADS);
|
||||
glColor3f(Nodes[I].B, Nodes[I].R, Nodes[I].G); { ╚этхЁЄшЁютрээ√щ ЎтхЄ фы ярЁ√ }
|
||||
glVertex3f(Nodes[I].X2 - S, Nodes[I].Y2 - S, Nodes[I].Z2 + S);
|
||||
glVertex3f(Nodes[I].X2 + S, Nodes[I].Y2 - S, Nodes[I].Z2 + S);
|
||||
glVertex3f(Nodes[I].X2 + S, Nodes[I].Y2 + S, Nodes[I].Z2 + S);
|
||||
glVertex3f(Nodes[I].X2 - S, Nodes[I].Y2 + S, Nodes[I].Z2 + S);
|
||||
glEnd();
|
||||
end;
|
||||
|
||||
kosglSwapBuffers();
|
||||
|
||||
UpdateDNAPhysics;
|
||||
Rotation := Rotation + Speed;
|
||||
TimeVal := TimeVal + 0.03;
|
||||
end;
|
||||
|
||||
begin
|
||||
TinyGL_initialization;
|
||||
|
||||
with GetScreenSize do
|
||||
begin
|
||||
WndWidth := Width div 3 * 2;
|
||||
WndHeight := Height div 3 * 2;
|
||||
WndLeft := (Width - WndWidth) div 2;
|
||||
WndTop := (Height - WndHeight) div 2;
|
||||
end;
|
||||
|
||||
while True do
|
||||
case WaitEventByTime(1) of
|
||||
REDRAW_EVENT:
|
||||
begin
|
||||
BeginDraw;
|
||||
DrawWindow(WndLeft, WndTop, WndWidth, WndHeight, '3D DNA Helix Wave', $00FFFFFF,
|
||||
WS_SKINNED_SIZABLE + WS_CLIENT_COORDS + WS_CAPTION, CAPTION_MOVABLE);
|
||||
GLDraw;
|
||||
EndDraw;
|
||||
end;
|
||||
KEY_EVENT: GetKey;
|
||||
BUTTON_EVENT: if GetButton.ID = 1 then ExitThread;
|
||||
else
|
||||
GLDraw;
|
||||
end;
|
||||
end.
|
||||
@@ -1,181 +0,0 @@
|
||||
program FractalStormForest;
|
||||
|
||||
uses
|
||||
KolibriOS, TinyGL;
|
||||
|
||||
const
|
||||
NUM_TREES = 7; // ъюышўхёЄтю фхЁхт№хт
|
||||
MAX_DEPTH = 5; // уыєсшэр ЇЁръЄрыр
|
||||
|
||||
var
|
||||
Rotation: GLFloat = 0;
|
||||
Speed: GLFloat = 0.5;
|
||||
ZTr: GLFloat = -11.0;
|
||||
TimeVal: GLFloat = 0;
|
||||
CTX: TKOSGLContext;
|
||||
|
||||
WndLeft, WndTop, WndWidth, WndHeight: LongInt;
|
||||
|
||||
// ═рёЄЁющър яхЁёяхъЄшт√ ърьхЁ√
|
||||
procedure Perspective(fovY, Aspect, zNear, zFar: GLDouble);
|
||||
var
|
||||
fW, fH, fovYPI360: GLDouble;
|
||||
M: array[0..15] of GLFloat;
|
||||
begin
|
||||
FillChar(M, SizeOf(M), #0);
|
||||
fovYPI360 := fovY * PI / 360;
|
||||
fH := Sin(fovYPI360) * zNear / Cos(fovYPI360);
|
||||
fW := fH * Aspect;
|
||||
M[0] := zNear / fW;
|
||||
M[5] := zNear / fH;
|
||||
M[10] := -(zFar + zNear) / (zFar - zNear);
|
||||
M[11] := -1;
|
||||
M[14] := -2 * zFar * zNear / (zFar - zNear);
|
||||
glLoadMatrixf(@M[0]);
|
||||
end;
|
||||
|
||||
procedure DrawBranch(Length: GLFloat; Depth: Integer; WindForce: GLFloat);
|
||||
var
|
||||
R, G, B: GLFloat;
|
||||
begin
|
||||
if Depth > MAX_DEPTH then Exit;
|
||||
|
||||
// ╬╤┼══▀▀ ╧└╦╚╥╨└ ╦╚╤╥┬█
|
||||
// ╤Єтюы Єхьэю-сюЁфют√щ }
|
||||
// ╩Ёюэр Ёъю-чюыюЄр / юЁрэцхтр }
|
||||
R := 0.3 + (Depth * 0.18);
|
||||
G := 0.05 + (Depth * 0.18);
|
||||
B := 0.1;
|
||||
|
||||
glBegin(GL_QUADS);
|
||||
glColor3f(R, G, B);
|
||||
glVertex3f(-0.1 * Length, 0.0, 0.1 * Length);
|
||||
glVertex3f( 0.1 * Length, 0.0, 0.1 * Length);
|
||||
glVertex3f( 0.05 * Length, Length, 0.05 * Length);
|
||||
glVertex3f(-0.05 * Length, Length, 0.05 * Length);
|
||||
|
||||
glColor3f(R * 0.8, G * 0.8, B * 0.8);
|
||||
glVertex3f( 0.1 * Length, 0.0, 0.1 * Length);
|
||||
glVertex3f( 0.1 * Length, 0.0, -0.1 * Length);
|
||||
glVertex3f( 0.05 * Length, Length, -0.05 * Length);
|
||||
glVertex3f( 0.05 * Length, Length, 0.05 * Length);
|
||||
|
||||
glColor3f(R * 0.6, G * 0.6, B * 0.6);
|
||||
glVertex3f( 0.1 * Length, 0.0, -0.1 * Length);
|
||||
glVertex3f(-0.1 * Length, 0.0, -0.1 * Length);
|
||||
glVertex3f(-0.05 * Length, Length, -0.05 * Length);
|
||||
glVertex3f( 0.05 * Length, Length, -0.05 * Length);
|
||||
|
||||
glColor3f(R * 0.7, G * 0.7, B * 0.7);
|
||||
glVertex3f(-0.1 * Length, 0.0, -0.1 * Length);
|
||||
glVertex3f(-0.1 * Length, 0.0, 0.1 * Length);
|
||||
glVertex3f(-0.05 * Length, Length, 0.05 * Length);
|
||||
glVertex3f(-0.05 * Length, Length, -0.05 * Length);
|
||||
glEnd();
|
||||
|
||||
glTranslatef(0.0, Length, 0.0);
|
||||
|
||||
glPushMatrix();
|
||||
glRotatef(22.0 + WindForce, 1.0, 0.0, 0.0);
|
||||
glRotatef(20.0, 0.0, 0.0, 1.0);
|
||||
glScalef(0.75, 0.75, 0.75);
|
||||
DrawBranch(Length, Depth + 1, WindForce * 1.25);
|
||||
glPopMatrix();
|
||||
|
||||
glPushMatrix();
|
||||
glRotatef(-22.0 + WindForce, 1.0, 0.0, 0.0);
|
||||
glRotatef(-20.0, 0.0, 0.0, 1.0);
|
||||
glScalef(0.75, 0.75, 0.75);
|
||||
DrawBranch(Length, Depth + 1, WindForce * 1.25);
|
||||
glPopMatrix();
|
||||
|
||||
glPushMatrix();
|
||||
glRotatef(30.0, 0.0, 1.0, 0.0);
|
||||
glRotatef(15.0 + WindForce, 0.0, 0.0, 1.0);
|
||||
glScalef(0.7, 0.7, 0.7);
|
||||
DrawBranch(Length, Depth + 1, WindForce * 1.15);
|
||||
glPopMatrix();
|
||||
end;
|
||||
|
||||
procedure GLDraw;
|
||||
var
|
||||
ThreadInfo: TThreadInfo;
|
||||
I: Integer;
|
||||
TreeAngle, Wind: GLFloat;
|
||||
begin
|
||||
GetThreadInfo($FFFFFFFF, ThreadInfo);
|
||||
if ThreadInfo.Client.Height <= 3 then Exit;
|
||||
|
||||
kosglMakeCurrent(0, 0, ThreadInfo.Client.Width, ThreadInfo.Client.Height, CTX);
|
||||
glViewPort(0, 0, ThreadInfo.Client.Width, ThreadInfo.Client.Height);
|
||||
|
||||
glClearColor(0.04, 0.04, 0.08, 0.0); // ╚ёёшэ -ўхЁэюх эхсю
|
||||
glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glLoadIdentity();
|
||||
Perspective(45.0, ThreadInfo.Client.Width / ThreadInfo.Client.Height, 0.1, 100.0);
|
||||
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glLoadIdentity();
|
||||
|
||||
glTranslatef(0.0, -1.2, ZTr);
|
||||
glRotatef(Rotation, 0.0, 1.0, 0.0);
|
||||
|
||||
glBegin(GL_QUADS);
|
||||
glColor3f(0.35, 0.30, 0.20);
|
||||
glVertex3f(-4.0, -1.0, 4.0); glVertex3f( 4.0, -1.0, 4.0);
|
||||
glVertex3f( 4.0, -1.0, -4.0); glVertex3f(-4.0, -1.0, -4.0);
|
||||
glEnd();
|
||||
|
||||
// ╧╬╨█┬╚╤╥█╔ ┬┼╥┼╨
|
||||
Wind := (Sin(TimeVal * 0.8) * 6.0) + (Sin(TimeVal * 2.5) * 3.5) + (Sin(TimeVal * 6.0) * 1.5);
|
||||
|
||||
for I := 0 to NUM_TREES - 1 do
|
||||
begin
|
||||
glPushMatrix();
|
||||
TreeAngle := (I * 360.0) / NUM_TREES;
|
||||
glRotatef(TreeAngle, 0.0, 1.0, 0.0);
|
||||
glTranslatef(0.0, -1.0, 2.2);
|
||||
|
||||
DrawBranch(2.0, 1, Wind);
|
||||
glPopMatrix();
|
||||
end;
|
||||
|
||||
kosglSwapBuffers();
|
||||
|
||||
Rotation := Rotation + Speed;
|
||||
TimeVal := TimeVal + 0.04;
|
||||
end;
|
||||
|
||||
begin
|
||||
TinyGL_initialization;
|
||||
|
||||
with GetScreenSize do
|
||||
begin
|
||||
WndWidth := Width div 3 * 2;
|
||||
WndHeight := Height div 3 * 2;
|
||||
WndLeft := (Width - WndWidth) div 2;
|
||||
WndTop := (Height - WndHeight) div 2;
|
||||
end;
|
||||
|
||||
while True do
|
||||
case WaitEventByTime(1) of
|
||||
REDRAW_EVENT:
|
||||
begin
|
||||
BeginDraw;
|
||||
DrawWindow(WndLeft, WndTop, WndWidth, WndHeight, 'TinyGL Autumn Storm', $00FFFFFF,
|
||||
WS_SKINNED_SIZABLE + WS_CLIENT_COORDS + WS_CAPTION, CAPTION_MOVABLE);
|
||||
GLDraw;
|
||||
EndDraw;
|
||||
end;
|
||||
KEY_EVENT:
|
||||
GetKey;
|
||||
BUTTON_EVENT:
|
||||
if GetButton.ID = 1 then
|
||||
ExitThread;
|
||||
else
|
||||
GLDraw;
|
||||
end;
|
||||
end.
|
||||
@@ -1,413 +0,0 @@
|
||||
program Perfect3DBalls;
|
||||
|
||||
uses
|
||||
KolibriOS, TinyGL;
|
||||
|
||||
const
|
||||
MAX_BALLS = 72;
|
||||
GRAVITY = 0.015;
|
||||
AIR = 0.99;
|
||||
BOUNCE = -0.85;
|
||||
|
||||
type
|
||||
TBall = record
|
||||
Active: Boolean;
|
||||
IsShard: Boolean;
|
||||
X, Y, Z: Single;
|
||||
VX, VY, VZ: Single;
|
||||
Radius: Single;
|
||||
Hue: Integer;
|
||||
Darkness: Single;
|
||||
Life: Single;
|
||||
end;
|
||||
|
||||
var
|
||||
WndLeft, WndTop, WndWidth, WndHeight: LongInt;
|
||||
CTX: TKOSGLContext;
|
||||
Balls: array[0..MAX_BALLS - 1] of TBall;
|
||||
Angle: Single = 0.0;
|
||||
|
||||
BOX_X, BOX_Y, BOX_Z: Single;
|
||||
i: Integer;
|
||||
|
||||
function Max(A, B: Extended): Extended; begin if A > B then Result := A else Result := B; end;
|
||||
function Min(A, B: Extended): Extended; begin if A < B then Result := A else Result := B; end;
|
||||
|
||||
procedure Perspective(fovY, Aspect, zNear, zFar: GLDouble);
|
||||
var
|
||||
fW, fH, fovYPI360: GLDouble;
|
||||
M: array[0..15] of GLFloat;
|
||||
begin
|
||||
FillChar(M, SizeOf(M), #0);
|
||||
fovYPI360 := fovY * PI / 360;
|
||||
fH := Sin(fovYPI360) * zNear / Cos(fovYPI360);
|
||||
fW := fH * Aspect;
|
||||
M[0] := zNear / fW;
|
||||
M[5] := zNear / fH;
|
||||
M[10] := -(zFar + zNear) / (zFar - zNear);
|
||||
M[11] := -1;
|
||||
M[14] := -2 * zFar * zNear / (zFar - zNear);
|
||||
glLoadMatrixf(@M[0]);
|
||||
end;
|
||||
|
||||
function Frac(N: Single): Single;
|
||||
begin
|
||||
Result := N - Trunc(N) ;
|
||||
end;
|
||||
|
||||
procedure HSLtoRGB(H: Integer; S, L: Single; var R, G, B: Single);
|
||||
var
|
||||
C, X, M, R1, G1, B1: Single;
|
||||
HPrime: Single;
|
||||
begin
|
||||
C := (1.0 - Abs(2.0 * L - 1.0)) * S;
|
||||
HPrime := H / 60.0;
|
||||
X := C * (1.0 - Abs(Frac(HPrime / 2.0) * 2.0 - 1.0));
|
||||
M := L - C / 2.0;
|
||||
if (HPrime >= 0) and (HPrime < 1) then begin R1 := C; G1 := X; B1 := 0; end
|
||||
else if (HPrime >= 1) and (HPrime < 2) then begin R1 := X; G1 := C; B1 := 0; end
|
||||
else if (HPrime >= 2) and (HPrime < 3) then begin R1 := 0; G1 := C; B1 := X; end
|
||||
else if (HPrime >= 3) and (HPrime < 4) then begin R1 := 0; G1 := X; B1 := C; end
|
||||
else if (HPrime >= 4) and (HPrime < 5) then begin R1 := X; G1 := 0; B1 := C; end
|
||||
else begin R1 := C; G1 := 0; B1 := X; end;
|
||||
R := R1 + M; G := G1 + M; B := B1 + M;
|
||||
end;
|
||||
|
||||
procedure DrawSphere(Radius: Single);
|
||||
var
|
||||
l_i, l_j: Integer;
|
||||
t_Segments: Integer;
|
||||
lat0, z0, r0, lat1, z1, r1: Single;
|
||||
lng, x, y: Single;
|
||||
begin
|
||||
t_Segments := 18;
|
||||
|
||||
for l_i := 0 to t_Segments - 1 do
|
||||
begin
|
||||
lat0 := PI * (-0.5 + l_i / t_Segments);
|
||||
z0 := Sin(lat0);
|
||||
r0 := Cos(lat0);
|
||||
|
||||
lat1 := PI * (-0.5 + (l_i + 1) / t_Segments);
|
||||
z1 := Sin(lat1);
|
||||
r1 := Cos(lat1);
|
||||
|
||||
glBegin(GL_QUAD_STRIP);
|
||||
for l_j := 0 to t_Segments do
|
||||
begin
|
||||
lng := 2.0 * PI * l_j / t_Segments;
|
||||
x := Cos(lng);
|
||||
y := Sin(lng);
|
||||
|
||||
glNormal3f(x * r0, y * r0, z0);
|
||||
glVertex3f(x * r0 * Radius, y * r0 * Radius, z0 * Radius);
|
||||
|
||||
glNormal3f(x * r1, y * r1, z1);
|
||||
glVertex3f(x * r1 * Radius, y * r1 * Radius, z1 * Radius);
|
||||
end;
|
||||
glEnd();
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure ResizeTopology(W, H: Integer);
|
||||
begin
|
||||
BOX_X := 5.0 * (W / H);
|
||||
BOX_Y := 5.0;
|
||||
BOX_Z := 5.0;
|
||||
end;
|
||||
|
||||
function FindFreeBallIndex: Integer;
|
||||
var
|
||||
K: Integer;
|
||||
begin
|
||||
Result := -1;
|
||||
for K := 0 to MAX_BALLS - 1 do
|
||||
begin
|
||||
if not Balls[K].Active then
|
||||
begin
|
||||
Result := K;
|
||||
Exit;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure SpawnBall(Index: Integer; IsShard: Boolean; ParentIndex: Integer);
|
||||
begin
|
||||
Balls[Index].Active := True;
|
||||
Balls[Index].IsShard := IsShard;
|
||||
Balls[Index].Darkness := 1.0;
|
||||
|
||||
if not IsShard then
|
||||
begin
|
||||
// ╧ю ты ■Єё т ёрьюь тхЁїє (BOX_Y) ш ярфр■Є тэшч
|
||||
Balls[Index].X := (Random * 100 / 100.0 - 0.5) * BOX_X * 1.6;
|
||||
Balls[Index].Y := BOX_Y - 0.5 - (Random * 100 / 50.0);
|
||||
Balls[Index].Z := (Random * 100 / 100.0 - 0.5) * BOX_Z * 1.6;
|
||||
Balls[Index].VX := (Random * 100 / 100.0 - 0.5) * 0.4;
|
||||
Balls[Index].VY := -(Random * 100 / 100.0) * 0.1; // ═ряЁртыхэшх тхъЄюЁр тэшч
|
||||
Balls[Index].VZ := (Random * 100 / 100.0 - 0.5) * 0.4;
|
||||
Balls[Index].Radius := 0.4 + (Random * 100 / 250.0);
|
||||
Balls[Index].Hue := Trunc(Random * 360);
|
||||
Balls[Index].Life := 1.0;
|
||||
end
|
||||
else
|
||||
begin
|
||||
Balls[Index].X := Balls[ParentIndex].X;
|
||||
Balls[Index].Y := Balls[ParentIndex].Y;
|
||||
Balls[Index].Z := Balls[ParentIndex].Z;
|
||||
Balls[Index].Radius := Balls[ParentIndex].Radius * 0.35;
|
||||
Balls[Index].Hue := Balls[ParentIndex].Hue;
|
||||
Balls[Index].Life := 1.0;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure UpdatePhysics;
|
||||
var
|
||||
Idx, J, FreeIdx: Integer;
|
||||
DX, DY, DZ, Dist, MinDist: Single;
|
||||
NX, NY, NZ, Overlap: Single;
|
||||
KX, KY, KZ, PFactor: Single;
|
||||
XS, YS, ZS: Single;
|
||||
begin
|
||||
for Idx := 0 to MAX_BALLS - 1 do
|
||||
begin
|
||||
if not Balls[Idx].Active then Continue;
|
||||
for J := Idx + 1 to MAX_BALLS - 1 do
|
||||
begin
|
||||
if not Balls[J].Active then Continue;
|
||||
DX := Balls[J].X - Balls[Idx].X;
|
||||
DY := Balls[J].Y - Balls[Idx].Y;
|
||||
DZ := Balls[J].Z - Balls[Idx].Z;
|
||||
Dist := Sqrt(DX * DX + DY * DY + DZ * DZ);
|
||||
MinDist := Balls[Idx].Radius + Balls[J].Radius;
|
||||
|
||||
if Dist < MinDist then
|
||||
begin
|
||||
if Dist > 0.001 then
|
||||
begin
|
||||
NX := DX / Dist; NY := DY / Dist; NZ := DZ / Dist;
|
||||
end
|
||||
else
|
||||
begin
|
||||
NX := 0.1; NY := 0.0; NZ := 0.0;
|
||||
end;
|
||||
Overlap := MinDist - Dist;
|
||||
Balls[Idx].X := Balls[Idx].X - NX * Overlap * 0.5;
|
||||
Balls[Idx].Y := Balls[Idx].Y - NY * Overlap * 0.5;
|
||||
Balls[Idx].Z := Balls[Idx].Z - NZ * Overlap * 0.5;
|
||||
Balls[J].X := Balls[J].X + NX * Overlap * 0.5;
|
||||
Balls[J].Y := Balls[J].Y + NY * Overlap * 0.5;
|
||||
Balls[J].Z := Balls[J].Z + NZ * Overlap * 0.5;
|
||||
KX := Balls[Idx].VX - Balls[J].VX;
|
||||
KY := Balls[Idx].VY - Balls[J].VY;
|
||||
KZ := Balls[Idx].VZ - Balls[J].VZ;
|
||||
PFactor := 2.0 * (NX * KX + NY * KY + NZ * KZ) / 2.0 + 0.01;
|
||||
Balls[Idx].VX := Balls[Idx].VX - PFactor * NX;
|
||||
Balls[Idx].VY := Balls[Idx].VY - PFactor * NY;
|
||||
Balls[Idx].VZ := Balls[Idx].VZ - PFactor * NZ;
|
||||
Balls[J].VX := Balls[J].VX + PFactor * NX;
|
||||
Balls[J].VY := Balls[J].VY + PFactor * NY;
|
||||
Balls[J].VZ := Balls[J].VZ + PFactor * NZ;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
for Idx := 0 to MAX_BALLS - 1 do
|
||||
begin
|
||||
if not Balls[Idx].Active then Continue;
|
||||
|
||||
Balls[Idx].VY := Balls[Idx].VY - GRAVITY;
|
||||
Balls[Idx].VX := Balls[Idx].VX * AIR;
|
||||
Balls[Idx].VY := Balls[Idx].VY * AIR;
|
||||
Balls[Idx].VZ := Balls[Idx].VZ * AIR;
|
||||
Balls[Idx].X := Balls[Idx].X + Balls[Idx].VX;
|
||||
Balls[Idx].Y := Balls[Idx].Y + Balls[Idx].VY;
|
||||
Balls[Idx].Z := Balls[Idx].Z + Balls[Idx].VZ;
|
||||
|
||||
if Balls[Idx].IsShard then
|
||||
begin
|
||||
Balls[Idx].Life := Balls[Idx].Life - 0.015;
|
||||
Balls[Idx].Darkness := Balls[Idx].Life;
|
||||
|
||||
if Balls[Idx].Y - Balls[Idx].Radius < -BOX_Y then
|
||||
begin
|
||||
Balls[Idx].Y := -BOX_Y + Balls[Idx].Radius; Balls[Idx].VY := Balls[Idx].VY * BOUNCE;
|
||||
end;
|
||||
if Balls[Idx].Y + Balls[Idx].Radius > BOX_Y then
|
||||
begin
|
||||
Balls[Idx].Y := BOX_Y - Balls[Idx].Radius; Balls[Idx].VY := Balls[Idx].VY * BOUNCE;
|
||||
end;
|
||||
if Balls[Idx].X - Balls[Idx].Radius < -BOX_X then
|
||||
begin
|
||||
Balls[Idx].X := -BOX_X + Balls[Idx].Radius; Balls[Idx].VX := Balls[Idx].VX * BOUNCE;
|
||||
end;
|
||||
if Balls[Idx].X + Balls[Idx].Radius > BOX_X then
|
||||
begin
|
||||
Balls[Idx].X := BOX_X - Balls[Idx].Radius; Balls[Idx].VX := Balls[Idx].VX * BOUNCE;
|
||||
end;
|
||||
if Balls[Idx].Z - Balls[Idx].Radius < -BOX_Z then
|
||||
begin
|
||||
Balls[Idx].Z := -BOX_Z + Balls[Idx].Radius; Balls[Idx].VZ := Balls[Idx].VZ * BOUNCE;
|
||||
end;
|
||||
if Balls[Idx].Z + Balls[Idx].Radius > BOX_Z then
|
||||
begin
|
||||
Balls[Idx].Z := BOX_Z - Balls[Idx].Radius; Balls[Idx].VZ := Balls[Idx].VZ * BOUNCE;
|
||||
end;
|
||||
if Balls[Idx].Life <= 0.0 then Balls[Idx].Active := False;
|
||||
end
|
||||
else
|
||||
begin
|
||||
// ╨рчЁє°хэшх сюы№°шї °рЁют яЁш ъюэЄръЄх ё ы■сющ шч 3D-уЁрэшЎ юъэр
|
||||
if (Balls[Idx].Y - Balls[Idx].Radius < -BOX_Y) or
|
||||
(Balls[Idx].Y + Balls[Idx].Radius > BOX_Y) or
|
||||
(Abs(Balls[Idx].X) + Balls[Idx].Radius > BOX_X) or
|
||||
(Abs(Balls[Idx].Z) + Balls[Idx].Radius > BOX_Z) then
|
||||
begin
|
||||
XS := -0.25;
|
||||
while XS <= 0.25 do
|
||||
begin
|
||||
YS := -0.25;
|
||||
while YS <= 0.25 do
|
||||
begin
|
||||
ZS := -0.25;
|
||||
while ZS <= 0.25 do
|
||||
begin
|
||||
FreeIdx := FindFreeBallIndex;
|
||||
if FreeIdx <> -1 then
|
||||
begin
|
||||
SpawnBall(FreeIdx, True, Idx);
|
||||
Balls[FreeIdx].VX := Balls[Idx].VX * 0.4 + XS * (1.0 + Random * 50 / 100.0);
|
||||
Balls[FreeIdx].VY := Balls[Idx].VY * BOUNCE + YS * (1.0 + Random * 50 / 100.0) + 0.15;
|
||||
Balls[FreeIdx].VZ := Balls[Idx].VZ * 0.4 + ZS * (1.0 + Random * 50 / 100.0);
|
||||
end;
|
||||
ZS := ZS + 0.5;
|
||||
end;
|
||||
YS := YS + 0.5;
|
||||
end;
|
||||
XS := XS + 0.5;
|
||||
end;
|
||||
SpawnBall(Idx, False, 0);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure GLDraw;
|
||||
var
|
||||
ThreadInfo: TThreadInfo;
|
||||
CosA, SinA: Single;
|
||||
LightPos: array[0..3] of GLfloat;
|
||||
LightAmbient: array[0..3] of GLfloat;
|
||||
LightDiffuse: array[0..3] of GLfloat;
|
||||
MatAmbient: array[0..3] of GLfloat;
|
||||
MatDiffuse: array[0..3] of GLfloat;
|
||||
MatSpecular: array[0..3] of GLfloat;
|
||||
R, G, B: Single;
|
||||
begin
|
||||
GetThreadInfo($FFFFFFFF, ThreadInfo);
|
||||
if not (ThreadInfo.Client.Height > 3) then Exit;
|
||||
|
||||
kosglMakeCurrent(0, 0, ThreadInfo.Client.Width, ThreadInfo.Client.Height, CTX);
|
||||
glViewPort(0, 0, ThreadInfo.Client.Width, ThreadInfo.Client.Height);
|
||||
|
||||
glClearColor(5/255, 6/255, 11/255, 0.0);
|
||||
glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glEnable(GL_LIGHTING);
|
||||
glEnable(GL_LIGHT0);
|
||||
|
||||
UpdatePhysics;
|
||||
ResizeTopology(ThreadInfo.Client.Width, ThreadInfo.Client.Height);
|
||||
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glLoadIdentity();
|
||||
Perspective(45.0, ThreadInfo.Client.Width / ThreadInfo.Client.Height, 0.1, 100.0);
|
||||
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glLoadIdentity();
|
||||
|
||||
Angle := Angle + 0.003;
|
||||
CosA := Cos(Angle); SinA := Sin(Angle);
|
||||
|
||||
glTranslatef(0.0, 0.0, -13.5);
|
||||
|
||||
// ═рёЄЁющър яючшЎшш ётхЄр (ёьх∙хэ ўєЄ№ т√°х фы ъЁрёштюую сышър)
|
||||
LightPos[0] := -8.0 * CosA - (-6.0) * SinA;
|
||||
LightPos[1] := 15.0; // ═ряЁртыхэ ётхЁїє тэшч
|
||||
LightPos[2] := -8.0 * SinA + (-6.0) * CosA;
|
||||
LightPos[3] := 0.5;
|
||||
|
||||
LightAmbient[0] := 0.35; LightAmbient[1] := 0.35; LightAmbient[2] := 0.38; LightAmbient[3] := 0.5;
|
||||
LightDiffuse[0] := 0.95; LightDiffuse[1] := 0.95; LightDiffuse[2] := 0.95; LightDiffuse[3] := 0.5;
|
||||
|
||||
glLightfv(GL_LIGHT0, GL_POSITION, @LightPos[0]);
|
||||
glLightfv(GL_LIGHT0, GL_AMBIENT, @LightAmbient[0]);
|
||||
glLightfv(GL_LIGHT0, GL_DIFFUSE, @LightDiffuse[0]);
|
||||
|
||||
MatSpecular[0] := 0.9; MatSpecular[1] := 0.9; MatSpecular[2] := 0.9; MatSpecular[3] := 0.5;
|
||||
glMaterialfv(GL_FRONT, GL_SPECULAR, @MatSpecular[0]);
|
||||
glMaterialf(GL_FRONT, GL_SHININESS, 64.0);
|
||||
|
||||
for i := 0 to MAX_BALLS - 1 do
|
||||
begin
|
||||
if not Balls[i].Active then Continue;
|
||||
|
||||
HSLtoRGB(Balls[i].Hue, 0.95, 0.55 * Balls[i].Darkness, R, G, B);
|
||||
|
||||
MatAmbient[0] := R * 0.6; MatAmbient[1] := G * 0.6; MatAmbient[2] := B * 0.6; MatAmbient[3] := 1.0;
|
||||
MatDiffuse[0] := R; MatDiffuse[1] := G; MatDiffuse[2] := B; MatDiffuse[3] := 1.0;
|
||||
|
||||
glMaterialfv(GL_FRONT, GL_AMBIENT, @MatAmbient[0]);
|
||||
glMaterialfv(GL_FRONT, GL_DIFFUSE, @MatDiffuse[0]);
|
||||
|
||||
glPushMatrix();
|
||||
glTranslatef(Balls[i].X, Balls[i].Y, Balls[i].Z);
|
||||
DrawSphere(Balls[i].Radius);
|
||||
glPopMatrix();
|
||||
end;
|
||||
|
||||
kosglSwapBuffers();
|
||||
end;
|
||||
|
||||
begin
|
||||
TinyGL_initialization;
|
||||
|
||||
Randomize;
|
||||
with GetScreenSize do
|
||||
begin
|
||||
WndWidth := Width div 3 * 2;
|
||||
WndHeight := Height div 3 * 2;
|
||||
WndLeft := (Width - WndWidth) div 2;
|
||||
WndTop := (Height - WndHeight) div 2;
|
||||
end;
|
||||
|
||||
ResizeTopology(WndWidth, WndHeight);
|
||||
|
||||
FillChar(Balls, SizeOf(Balls), #0);
|
||||
for i := 0 to 24 do
|
||||
begin
|
||||
SpawnBall(i, False, 0);
|
||||
// ╨рёяЁхфхы хь ЁртэюьхЁэю яю тёхщ т√ёюЄх ъюЁюсъш (юЄ -BOX_Y фю BOX_Y)
|
||||
Balls[i].Y := -BOX_Y + 1.0 + (Random * 100 / 100.0) * (BOX_Y * 2.0 - 2.0);
|
||||
end;
|
||||
|
||||
while True do
|
||||
case WaitEventByTime(1) of
|
||||
REDRAW_EVENT:
|
||||
begin
|
||||
BeginDraw;
|
||||
DrawWindow(WndLeft, WndTop, WndWidth, WndHeight, 'TinyGL Light 3D Balls', $00FFFFFF,
|
||||
WS_SKINNED_SIZABLE + WS_CLIENT_COORDS + WS_CAPTION, CAPTION_MOVABLE);
|
||||
GLDraw;
|
||||
EndDraw;
|
||||
end;
|
||||
KEY_EVENT:
|
||||
GetKey;
|
||||
BUTTON_EVENT:
|
||||
if GetButton.ID = 1 then
|
||||
ExitThread;
|
||||
else
|
||||
GLDraw;
|
||||
end;
|
||||
end.
|
||||
@@ -1,22 +0,0 @@
|
||||
#SHS
|
||||
rm Bublick_TinyGL.kex
|
||||
rm CircleParticles_TinyGL.kex
|
||||
rm DNAHelix3D_TinyGL.kex
|
||||
rm FractalStormForest_TinyGL.kex
|
||||
rm GravityShardBalls_TinyGL.kex
|
||||
rm MengerSponge_TinyGL.kex
|
||||
rm RubikRotate3D.kex
|
||||
rm Sierpinski3D_TinyGL.kex
|
||||
rm WaveMesh_TinyGL.kex
|
||||
rm XDRUSH.kex
|
||||
../xdpk.kex Bublick_TinyGL.pas
|
||||
../xdpk.kex CircleParticles_TinyGL.pas
|
||||
../xdpk.kex DNAHelix3D_TinyGL.pas
|
||||
../xdpk.kex FractalStormForest_TinyGL.pas
|
||||
../xdpk.kex GravityShardBalls_TinyGL.pas
|
||||
../xdpk.kex MengerSponge_TinyGL.pas
|
||||
../xdpk.kex RubikRotate3D.pas
|
||||
../xdpk.kex Sierpinski3D_TinyGL.pas
|
||||
../xdpk.kex WaveMesh_TinyGL.pas
|
||||
../xdpk.kex XDRUSH.pas
|
||||
exit
|
||||
@@ -1,207 +0,0 @@
|
||||
program MengerSpongeFractal;
|
||||
|
||||
uses
|
||||
KolibriOS, TinyGL;
|
||||
|
||||
const
|
||||
MAX_DEPTH = 2; { ├ыєсшэр ЇЁръЄрыр. ┬эшьрэшх: чэрўхэшх 3 чрЄюЁьючшЄ ёЄрЁ√щ яЁюЎхёёюЁ }
|
||||
|
||||
var
|
||||
Rotation: GLFloat = 0;
|
||||
Speed: GLFloat = 0.835;
|
||||
ZTr: GLFloat = -5.0;
|
||||
TimeVal: GLFloat = 0;
|
||||
CTX: TKOSGLContext;
|
||||
|
||||
WndLeft, WndTop, WndWidth, WndHeight: LongInt;
|
||||
|
||||
IsLine: Boolean;
|
||||
|
||||
// ═рёЄЁющър яхЁёяхъЄшт√ ърьхЁ√
|
||||
procedure Perspective(fovY, Aspect, zNear, zFar: GLDouble);
|
||||
var
|
||||
fW, fH, fovYPI360: GLDouble;
|
||||
M: array[0..15] of GLFloat;
|
||||
begin
|
||||
FillChar(M, SizeOf(M), #0);
|
||||
fovYPI360 := fovY * PI / 360;
|
||||
fH := Sin(fovYPI360) * zNear / Cos(fovYPI360);
|
||||
fW := fH * Aspect;
|
||||
M[0] := zNear / fW;
|
||||
M[5] := zNear / fH;
|
||||
M[10] := -(zFar + zNear) / (zFar - zNear);
|
||||
M[11] := -1;
|
||||
M[14] := -2 * zFar * zNear / (zFar - zNear);
|
||||
glLoadMatrixf(@M[0]);
|
||||
end;
|
||||
|
||||
// ╬ЄЁшёютър срчютюую ъєср ЇЁръЄрыр ё яёхтфю-юётх∙хэшхь уЁрэхщ
|
||||
procedure DrawSolidCube(Size: GLFloat);
|
||||
var
|
||||
S: GLFloat;
|
||||
begin
|
||||
S := Size * 0.5;
|
||||
glBegin(GL_QUADS);
|
||||
// ╧хЁхфэ уЁрэ№ - ▀Ёър сшЁ■чютр
|
||||
if not IsLine then
|
||||
glColor3f(0.1, 0.7, 0.8)
|
||||
else
|
||||
glColor3f(0.5, 0.5, 0.5);
|
||||
glVertex3f(-S, -S, S); glVertex3f( S, -S, S);
|
||||
glVertex3f( S, S, S); glVertex3f(-S, S, S);
|
||||
// ╟рфэ уЁрэ№ - ╤шэ
|
||||
if not IsLine then
|
||||
glColor3f(0.05, 0.4, 0.6)
|
||||
else
|
||||
glColor3f(0.5, 0.5, 0.5);
|
||||
glVertex3f(-S, -S, -S); glVertex3f(-S, S, -S);
|
||||
glVertex3f( S, S, -S); glVertex3f( S, -S, -S);
|
||||
// ┬хЁїэ уЁрэ№ - ╤тхЄыю-уюыєср
|
||||
if not IsLine then
|
||||
glColor3f(0.2, 0.8, 1.0)
|
||||
else
|
||||
glColor3f(0.5, 0.5, 0.5);
|
||||
glVertex3f(-S, S, -S); glVertex3f(-S, S, S);
|
||||
glVertex3f( S, S, S); glVertex3f( S, S, -S);
|
||||
// ═шцэ уЁрэ№ - ╥хьэю-ёшэ
|
||||
if not IsLine then
|
||||
glColor3f(0.02, 0.2, 0.4)
|
||||
else
|
||||
glColor3f(0.5, 0.5, 0.5);
|
||||
glVertex3f(-S, -S, -S); glVertex3f( S, -S, -S);
|
||||
glVertex3f( S, -S, S); glVertex3f(-S, -S, S);
|
||||
// ╧Ёртр уЁрэ№ }
|
||||
if not IsLine then
|
||||
glColor3f(0.08, 0.5, 0.7)
|
||||
else
|
||||
glColor3f(0.5, 0.5, 0.5);
|
||||
glVertex3f( S, -S, -S); glVertex3f( S, S, -S);
|
||||
glVertex3f( S, S, S); glVertex3f( S, -S, S);
|
||||
// ╦хтр уЁрэ№ }
|
||||
if not IsLine then
|
||||
glColor3f(0.06, 0.45, 0.65)
|
||||
else
|
||||
glColor3f(0.5, 0.5, 0.5);
|
||||
glVertex3f(-S, -S, -S); glVertex3f(-S, -S, S);
|
||||
glVertex3f(-S, S, S); glVertex3f(-S, S, -S);
|
||||
glEnd();
|
||||
end;
|
||||
|
||||
// ╨хъєЁёштэ√щ рыуюЁшЄь ухэхЁрЎшш ├єсъш ╠хэухЁр
|
||||
procedure BuildSponge(X, Y, Z, Size: GLFloat; Depth: Integer);
|
||||
var
|
||||
NewSize: GLFloat;
|
||||
dx, dy, dz: Integer;
|
||||
Sum: Integer;
|
||||
begin
|
||||
// ┼ёыш фю°ыш фю яЁхфхыр ЁхъєЁёшш Ч Ёшёєхь ёяыю°эющ ъєсшъ т ¤Єшї ъююЁфшэрЄрї
|
||||
if Depth = MAX_DEPTH then
|
||||
begin
|
||||
glPushMatrix();
|
||||
glTranslatef(X, Y, Z);
|
||||
DrawSolidCube(Size);
|
||||
glPopMatrix();
|
||||
end
|
||||
else
|
||||
begin
|
||||
NewSize := Size / 3.0;
|
||||
// ╧хЁхсшЁрхь ёхЄъє 3x3x3
|
||||
for dx := -1 to 1 do
|
||||
for dy := -1 to 1 do
|
||||
for dz := -1 to 1 do
|
||||
begin
|
||||
// ┬√ўшёы хь ьрЄхьрЄшўхёъюх єёыютшх яєёЄюЄ√ фы ├єсъш ╠хэухЁр
|
||||
Sum := 0;
|
||||
if dx = 0 then Inc(Sum);
|
||||
if dy = 0 then Inc(Sum);
|
||||
if dz = 0 then Inc(Sum);
|
||||
// ┼ёыш сюыхх ўхь юфэр ъююЁфшэрЄр Ёртэр 0, ¤Єю ёътючэюх юЄтхЁёЄшх Ч яЁюяєёърхь хую
|
||||
if Sum < 2 then
|
||||
begin
|
||||
BuildSponge(
|
||||
X + dx * NewSize,
|
||||
Y + dy * NewSize,
|
||||
Z + dz * NewSize,
|
||||
NewSize,
|
||||
Depth + 1
|
||||
);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure GLDraw;
|
||||
var
|
||||
ThreadInfo: TThreadInfo;
|
||||
Pulse: GLFloat;
|
||||
begin
|
||||
GetThreadInfo($FFFFFFFF, ThreadInfo);
|
||||
if ThreadInfo.Client.Height <= 3 then Exit;
|
||||
|
||||
kosglMakeCurrent(0, 0, ThreadInfo.Client.Width, ThreadInfo.Client.Height, CTX);
|
||||
glViewPort(0, 0, ThreadInfo.Client.Width, ThreadInfo.Client.Height);
|
||||
|
||||
glClearColor(0.03, 0.04, 0.06, 0.0); // ├ыєсюъшщ ъюёьшўхёъшщ Їюэ
|
||||
glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glEnable(GL_CULL_FACE);
|
||||
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glLoadIdentity();
|
||||
Perspective(45.0, ThreadInfo.Client.Width / ThreadInfo.Client.Height, 0.1, 100.0);
|
||||
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glLoadIdentity();
|
||||
|
||||
glTranslatef(0.0, 0.0, ZTr);
|
||||
|
||||
// ┬Ёр∙рхь ЇЁръЄры яю фтєь юё ь фы яюыэюЎхээюую 3D юсчюЁр
|
||||
glRotatef(Rotation, 0.5, 1.0, 0.2);
|
||||
|
||||
// ┬√ўшёы хь Їшчшўхёъє■ яєы№ёрЎш■ ЁрчьхЁр юЄ тЁхьхэш
|
||||
Pulse := 1.8 + Sin(TimeVal) * 0.25;
|
||||
|
||||
// ╟ряєёъ ухэхЁрЎшш ЇЁръЄрыр шч ЎхэЄЁр (0,0,0) ё фшэрьшўхёъшь ЁрчьхЁюь
|
||||
IsLine := False;
|
||||
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); // Ёшёєхь ё чрыштъющ
|
||||
BuildSponge(0.0, 0.0, 0.0, Pulse, 0);
|
||||
IsLine := True;
|
||||
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); // Ёшёєхь ъюэЄєЁэ√х ышэшш
|
||||
BuildSponge(0.0, 0.0, 0.0, Pulse, 0);
|
||||
|
||||
kosglSwapBuffers();
|
||||
|
||||
Rotation := Rotation + Speed;
|
||||
TimeVal := TimeVal + 0.03;
|
||||
end;
|
||||
|
||||
begin
|
||||
TinyGL_initialization;
|
||||
|
||||
with GetScreenSize do
|
||||
begin
|
||||
WndWidth := Width div 3 * 2;
|
||||
WndHeight := Height div 3 * 2;
|
||||
WndLeft := (Width - WndWidth) div 2;
|
||||
WndTop := (Height - WndHeight) div 2;
|
||||
end;
|
||||
|
||||
while True do
|
||||
case WaitEventByTime(1) of
|
||||
REDRAW_EVENT:
|
||||
begin
|
||||
BeginDraw;
|
||||
DrawWindow(WndLeft, WndTop, WndWidth, WndHeight, 'Menger Sponge 3D Fractal', $00FFFFFF,
|
||||
WS_SKINNED_SIZABLE + WS_CLIENT_COORDS + WS_CAPTION, CAPTION_MOVABLE);
|
||||
GLDraw;
|
||||
EndDraw;
|
||||
end;
|
||||
KEY_EVENT:
|
||||
GetKey;
|
||||
BUTTON_EVENT:
|
||||
if GetButton.ID = 1 then
|
||||
ExitThread;
|
||||
else
|
||||
GLDraw;
|
||||
end;
|
||||
end.
|
||||
@@ -1,218 +0,0 @@
|
||||
program ParticleCubeFountain;
|
||||
|
||||
uses
|
||||
KolibriOS, TinyGL;
|
||||
|
||||
const
|
||||
MAX_PARTICLES = 100; // ьръёшьры№эюх ъюышўхёЄтю ъєсшъют
|
||||
|
||||
// ═└╤╥╨╬╔╩└ ╘╚╟╚╩╚
|
||||
GRAVITY = 0.0066; // ╤шыр Є цхёЄш: ўхь ьхэ№°х, Єхь т√°х тчыхЄрхЄ ЇюэЄрэ
|
||||
BOUNCE_FACTOR = 0.70; // ╩ю¤ЇЇшЎшхэЄ юЄёъюър: 0.70 ючэрўрхЄ ёюїЁрэхэшх 70% т√ёюЄ√ яЁ√цър
|
||||
FLOOR_Y = -3.0; // ╙Ёютхэ№ яюыр, юЄ ъюЄюЁюую юЄёъръштр■Є ъєсшъш
|
||||
|
||||
type
|
||||
TParticle = record
|
||||
X, Y, Z: GLFloat;
|
||||
VX, VY, VZ: GLFloat;
|
||||
R, G, B: GLFloat;
|
||||
Life: GLFloat;
|
||||
end;
|
||||
|
||||
var
|
||||
Particles: array[1..MAX_PARTICLES] of TParticle;
|
||||
Rotation: GLFloat = 0;
|
||||
Speed: GLFloat = 0.8;
|
||||
ZTr: GLFloat = -15.0;
|
||||
CTX: TKOSGLContext;
|
||||
|
||||
WndLeft, WndTop, WndWidth, WndHeight: LongInt;
|
||||
|
||||
// ═рёЄЁющър яхЁёяхъЄшт√ ърьхЁ√
|
||||
procedure Perspective(fovY, Aspect, zNear, zFar: GLDouble);
|
||||
var
|
||||
fW, fH, fovYPI360: GLDouble;
|
||||
M: array[0..15] of GLFloat;
|
||||
begin
|
||||
FillChar(M, SizeOf(M), #0);
|
||||
fovYPI360 := fovY * PI / 360;
|
||||
fH := Sin(fovYPI360) * zNear / Cos(fovYPI360);
|
||||
fW := fH * Aspect;
|
||||
M[0] := zNear / fW;
|
||||
M[5] := zNear / fH;
|
||||
M[10] := -(zFar + zNear) / (zFar - zNear);
|
||||
M[11] := -1;
|
||||
M[14] := -2 * zFar * zNear / (zFar - zNear);
|
||||
glLoadMatrixf(@M[0]);
|
||||
end;
|
||||
|
||||
procedure ResetParticle(Index: Integer);
|
||||
begin
|
||||
Particles[Index].X := 0.0;
|
||||
Particles[Index].Y := -1.5;
|
||||
Particles[Index].Z := 0.0;
|
||||
|
||||
Particles[Index].VX := ((Index mod 11) - 5) * 0.012;
|
||||
Particles[Index].VY := 0.10 + (Index mod 7) * 0.012; // ═рўры№эр ёъюЁюёЄ№ ттхЁї
|
||||
Particles[Index].VZ := ((Index mod 13) - 6) * 0.012;
|
||||
|
||||
// ═рё√∙хээ√х ЎтхЄр (ёьхё№ ЇшюыхЄютюую, ёшэхую ш сшЁ■чютюую фы ЁрчэююсЁрчш )
|
||||
Particles[Index].R := 0.2 + (Index mod 4) * 0.2;
|
||||
Particles[Index].G := 0.4 + (Index mod 6) * 0.1;
|
||||
Particles[Index].B := 0.8 + (Index mod 3) * 0.1;
|
||||
|
||||
Particles[Index].Life := 1.0;
|
||||
end;
|
||||
|
||||
procedure InitParticles;
|
||||
var
|
||||
I: Integer;
|
||||
begin
|
||||
for I := 1 to MAX_PARTICLES do
|
||||
ResetParticle(I);
|
||||
end;
|
||||
|
||||
procedure UpdatePhysics;
|
||||
var
|
||||
I: Integer;
|
||||
begin
|
||||
for I := 1 to MAX_PARTICLES do
|
||||
begin
|
||||
Particles[I].X := Particles[I].X + Particles[I].VX;
|
||||
Particles[I].Y := Particles[I].Y + Particles[I].VY;
|
||||
Particles[I].Z := Particles[I].Z + Particles[I].VZ;
|
||||
|
||||
// ╧Ёшьхэ хь эрёЄЁрштрхьє■ уЁртшЄрЎш■
|
||||
Particles[I].VY := Particles[I].VY - GRAVITY;
|
||||
|
||||
// ╬Єёъюъ юЄ яюыр ё єўхЄюь эрёЄЁрштрхь√ї ярЁрьхЄЁют
|
||||
if Particles[I].Y < FLOOR_Y then
|
||||
begin
|
||||
Particles[I].Y := FLOOR_Y;
|
||||
Particles[I].VY := -Particles[I].VY * BOUNCE_FACTOR;
|
||||
end;
|
||||
|
||||
Particles[I].Life := Particles[I].Life - 0.006;
|
||||
|
||||
if Particles[I].Life <= 0.0 then
|
||||
ResetParticle(I);
|
||||
end;
|
||||
end;
|
||||
|
||||
// яЁюЎхфєЁр юЄЁшёютъш 3D-ъєср ё уЁрэ ьш
|
||||
procedure DrawCube(R, G, B: GLFloat);
|
||||
begin
|
||||
glBegin(GL_QUADS);
|
||||
// ╧хЁхфэ уЁрэ№
|
||||
glColor3f(R, G, B);
|
||||
glVertex3f(-1.0, -1.0, 1.0); glVertex3f( 1.0, -1.0, 1.0);
|
||||
glVertex3f( 1.0, 1.0, 1.0); glVertex3f(-1.0, 1.0, 1.0);
|
||||
// ╟рфэ уЁрэ№
|
||||
glColor3f(R * 0.8, G * 0.8, B * 0.8); // ╫єЄ№ Єхьэхх фы юс·хьр
|
||||
glVertex3f(-1.0, -1.0, -1.0); glVertex3f(-1.0, 1.0, -1.0);
|
||||
glVertex3f( 1.0, 1.0, -1.0); glVertex3f( 1.0, -1.0, -1.0);
|
||||
// ┬хЁїэ уЁрэ№
|
||||
glColor3f(R * 0.9, G * 0.9, B * 0.9);
|
||||
glVertex3f(-1.0, 1.0, -1.0); glVertex3f(-1.0, 1.0, 1.0);
|
||||
glVertex3f( 1.0, 1.0, 1.0); glVertex3f( 1.0, 1.0, -1.0);
|
||||
// ═шцэ уЁрэ№
|
||||
glColor3f(R * 0.6, G * 0.6, B * 0.6);
|
||||
glVertex3f(-1.0, -1.0, -1.0); glVertex3f( 1.0, -1.0, -1.0);
|
||||
glVertex3f( 1.0, -1.0, 1.0); glVertex3f(-1.0, -1.0, 1.0);
|
||||
// ╧Ёртр уЁрэ№
|
||||
glColor3f(R * 0.85, G * 0.85, B * 0.85);
|
||||
glVertex3f( 1.0, -1.0, -1.0); glVertex3f( 1.0, 1.0, -1.0);
|
||||
glVertex3f( 1.0, 1.0, 1.0); glVertex3f( 1.0, -1.0, 1.0);
|
||||
// ╦хтр уЁрэ№
|
||||
glColor3f(R * 0.75, G * 0.75, B * 0.75);
|
||||
glVertex3f(-1.0, -1.0, -1.0); glVertex3f(-1.0, -1.0, 1.0);
|
||||
glVertex3f(-1.0, 1.0, 1.0); glVertex3f(-1.0, 1.0, -1.0);
|
||||
glEnd();
|
||||
end;
|
||||
|
||||
procedure GLDraw;
|
||||
var
|
||||
ThreadInfo: TThreadInfo;
|
||||
I: Integer;
|
||||
begin
|
||||
GetThreadInfo($FFFFFFFF, ThreadInfo);
|
||||
if ThreadInfo.Client.Height <= 3 then Exit;
|
||||
|
||||
kosglMakeCurrent(0, 0, ThreadInfo.Client.Width, ThreadInfo.Client.Height, CTX);
|
||||
glViewPort(0, 0, ThreadInfo.Client.Width, ThreadInfo.Client.Height);
|
||||
|
||||
glClearColor(0.05, 0.05, 0.1, 0.0); // ├ыєсюъшщ яюыєэюўэ√щ Їюэ
|
||||
glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glLoadIdentity();
|
||||
Perspective(45.0, ThreadInfo.Client.Width / ThreadInfo.Client.Height, 0.1, 100.0);
|
||||
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glLoadIdentity();
|
||||
|
||||
glTranslatef(0.0, 0.0, ZTr);
|
||||
glRotatef(Rotation, 0.0, 1.0, 0.0); // ┬Ёр∙хэшх ёЎхэ√ яю юёш Y
|
||||
|
||||
// ╬ЄЁшёютър яыюёъюёЄш яюыр
|
||||
glBegin(GL_QUADS);
|
||||
glColor3f(0.25, 0.25, 0.45);
|
||||
glVertex3f(-6.0, FLOOR_Y, 6.0);
|
||||
glVertex3f( 6.0, FLOOR_Y, 6.0);
|
||||
glVertex3f( 6.0, FLOOR_Y, -6.0);
|
||||
glVertex3f(-6.0, FLOOR_Y, -6.0);
|
||||
glEnd();
|
||||
|
||||
// ╓шъы юЄЁшёютъш 3D-ъєсшъют
|
||||
for I := 1 to MAX_PARTICLES do
|
||||
begin
|
||||
glPushMatrix();
|
||||
glTranslatef(Particles[I].X, Particles[I].Y, Particles[I].Z);
|
||||
// ┬Ёр∙рхь ърцф√щ ъєсшъ тюъЁєу ётюхщ юёш фы фшэрьшъш
|
||||
glRotatef(Rotation * 2.5 + I, 0.4, 0.8, 0.2);
|
||||
// ╠рё°ЄрсшЁєхь ъєс яЁюяюЁЎшюэры№эю хую тЁхьхэш цшчэш
|
||||
glScalef(Particles[I].Life * 0.25, Particles[I].Life * 0.25, Particles[I].Life * 0.25);
|
||||
// ┬√чют ърёЄюьэющ юЄЁшёютъш ухюьхЄЁшш
|
||||
DrawCube(Particles[I].R, Particles[I].G, Particles[I].B);
|
||||
glPopMatrix();
|
||||
end;
|
||||
|
||||
kosglSwapBuffers();
|
||||
|
||||
UpdatePhysics;
|
||||
Rotation := Rotation + Speed;
|
||||
end;
|
||||
|
||||
begin
|
||||
TinyGL_initialization;
|
||||
|
||||
InitParticles;
|
||||
|
||||
with GetScreenSize do
|
||||
begin
|
||||
WndWidth := Width div 3 * 2;
|
||||
WndHeight := Height div 3 * 2;
|
||||
WndLeft := (Width - WndWidth) div 2;
|
||||
WndTop := (Height - WndHeight) div 2;
|
||||
end;
|
||||
|
||||
while True do
|
||||
case WaitEventByTime(1) of
|
||||
REDRAW_EVENT:
|
||||
begin
|
||||
BeginDraw;
|
||||
DrawWindow(WndLeft, WndTop, WndWidth, WndHeight, 'TinyGL 3D Cube Fountain', $00FFFFFF,
|
||||
WS_SKINNED_SIZABLE + WS_CLIENT_COORDS + WS_CAPTION, CAPTION_MOVABLE);
|
||||
GLDraw;
|
||||
EndDraw;
|
||||
end;
|
||||
KEY_EVENT:
|
||||
GetKey;
|
||||
BUTTON_EVENT:
|
||||
if GetButton.ID = 1 then
|
||||
ExitThread;
|
||||
else
|
||||
GLDraw;
|
||||
end;
|
||||
end.
|
||||
@@ -1,226 +0,0 @@
|
||||
program RubikRotate3D;
|
||||
|
||||
uses
|
||||
KolibriOS, TinyGL;
|
||||
|
||||
const
|
||||
CUBE_DIST = 0.72; // ╨рёёЄю эшх ьхцфє ЎхэЄЁрьш ъєсшъют
|
||||
|
||||
type
|
||||
TVertex3D = record
|
||||
X, Y, Z: GLFloat;
|
||||
end;
|
||||
|
||||
var
|
||||
Rotation: GLFloat = 0;
|
||||
CamSpeed: GLFloat = 0.5;
|
||||
ZTr: GLFloat = -6.5;
|
||||
TimeVal: GLFloat = 0;
|
||||
|
||||
// ╧рЁрьхЄЁ√ рэшьрЎшш ёыюхт
|
||||
LayerAngle: GLFloat = 0;
|
||||
ActiveAxis: Integer = 0; // 0 = X, 1 = Y, 2 = Z
|
||||
ActiveLayer: Integer = -1; // -1 = ыхт√щ, 0 = ЎхэЄЁры№э√щ, 1 = яЁрт√щ
|
||||
|
||||
CTX: TKOSGLContext;
|
||||
WndLeft, WndTop, WndWidth, WndHeight: LongInt;
|
||||
|
||||
// ═рёЄЁющър яхЁёяхъЄшт√ ърьхЁ√
|
||||
procedure Perspective(fovY, Aspect, zNear, zFar: GLDouble);
|
||||
var
|
||||
fW, fH, fovYPI360: GLDouble;
|
||||
M: array[0..15] of GLFloat;
|
||||
begin
|
||||
FillChar(M, SizeOf(M), #0);
|
||||
fovYPI360 := fovY * PI / 360;
|
||||
fH := Sin(fovYPI360) * zNear / Cos(fovYPI360);
|
||||
fW := fH * Aspect;
|
||||
M[0] := zNear / fW;
|
||||
M[5] := zNear / fH;
|
||||
M[10] := -(zFar + zNear) / (zFar - zNear);
|
||||
M[11] := -1;
|
||||
M[14] := -2 * zFar * zNear / (zFar - zNear);
|
||||
glLoadMatrixf(@M[0]);
|
||||
end;
|
||||
|
||||
// тЁр∙хэшх юфэющ 3D Єюўъш яю юё ь X, Y шыш Z
|
||||
procedure RotatePoint(var Px, Py, Pz: GLFloat; Axis: Integer; AngleDegrees: GLFloat);
|
||||
var
|
||||
Rad, CosA, SinA, Tx, Ty, Tz: GLFloat;
|
||||
begin
|
||||
Rad := AngleDegrees * PI / 180.0;
|
||||
CosA := Cos(Rad);
|
||||
SinA := Sin(Rad);
|
||||
Tx := Px; Ty := Py; Tz := Pz;
|
||||
|
||||
if Axis = 0 then { ┬юъЁєу X }
|
||||
begin
|
||||
Py := Ty * CosA - Tz * SinA;
|
||||
Pz := Ty * SinA + Tz * CosA;
|
||||
end
|
||||
else if Axis = 1 then { ┬юъЁєу Y }
|
||||
begin
|
||||
Px := Tx * CosA + Tz * SinA;
|
||||
Pz := -Tx * SinA + Tz * CosA;
|
||||
end
|
||||
else if Axis = 2 then { ┬юъЁєу Z }
|
||||
begin
|
||||
Px := Tx * CosA - Ty * SinA;
|
||||
Py := Tx * SinA + Ty * CosA;
|
||||
end;
|
||||
end;
|
||||
|
||||
// ╬ЄЁшёютър ъєср ё тэ√ь ЁрёўхЄюь 8 тхЁ°шэ
|
||||
procedure DrawSubCube(S: GLFloat; GridX, GridY, GridZ: Integer; R, G, B: GLFloat);
|
||||
var
|
||||
Pts: array[0..7] of TVertex3D;
|
||||
I: Integer;
|
||||
IsLayerActive: Boolean;
|
||||
begin
|
||||
IsLayerActive := False;
|
||||
if (ActiveAxis = 0) and (GridX = ActiveLayer) then IsLayerActive := True;
|
||||
if (ActiveAxis = 1) and (GridY = ActiveLayer) then IsLayerActive := True;
|
||||
if (ActiveAxis = 2) and (GridZ = ActiveLayer) then IsLayerActive := True;
|
||||
|
||||
// ╟рфрхь ыюъры№э√х ъююЁфшэрЄ√ ъєср
|
||||
Pts[0].X := -S; Pts[0].Y := -S; Pts[0].Z := S;
|
||||
Pts[1].X := S; Pts[1].Y := -S; Pts[1].Z := S;
|
||||
Pts[2].X := S; Pts[2].Y := S; Pts[2].Z := S;
|
||||
Pts[3].X := -S; Pts[3].Y := S; Pts[3].Z := S;
|
||||
Pts[4].X := -S; Pts[4].Y := -S; Pts[4].Z := -S;
|
||||
Pts[5].X := -S; Pts[5].Y := S; Pts[5].Z := -S;
|
||||
Pts[6].X := S; Pts[6].Y := S; Pts[6].Z := -S;
|
||||
Pts[7].X := S; Pts[7].Y := -S; Pts[7].Z := -S;
|
||||
|
||||
for I := 0 to 7 do
|
||||
begin
|
||||
// 1. ╤эрўрыр ёфтшурхь ¤ыхьхэЄ√ эр Ёрфшєё юЁсшЄ√
|
||||
Pts[I].X := Pts[I].X + (GridX * CUBE_DIST);
|
||||
Pts[I].Y := Pts[I].Y + (GridY * CUBE_DIST);
|
||||
Pts[I].Z := Pts[I].Z + (GridZ * CUBE_DIST);
|
||||
|
||||
// 2. ┼ёыш ъєсшъ т ръЄштэюь ёыюх, тЁр∙рхь хую ёЄЁюую т ыюъры№э√ї юё ї
|
||||
if IsLayerActive then
|
||||
RotatePoint(Pts[I].X, Pts[I].Y, Pts[I].Z, ActiveAxis, LayerAngle);
|
||||
end;
|
||||
|
||||
{ ┬√тюфшь 6 уЁрэхщ }
|
||||
glBegin(GL_QUADS);
|
||||
{ ╧хЁхфэ }
|
||||
glColor3f(R, G, B);
|
||||
glVertex3f(Pts[0].X, Pts[0].Y, Pts[0].Z); glVertex3f(Pts[1].X, Pts[1].Y, Pts[1].Z);
|
||||
glVertex3f(Pts[2].X, Pts[2].Y, Pts[2].Z); glVertex3f(Pts[3].X, Pts[3].Y, Pts[3].Z);
|
||||
{ ╟рфэ }
|
||||
glColor3f(R * 0.5, G * 0.5, B * 0.5);
|
||||
glVertex3f(Pts[4].X, Pts[4].Y, Pts[4].Z); glVertex3f(Pts[5].X, Pts[5].Y, Pts[5].Z);
|
||||
glVertex3f(Pts[6].X, Pts[6].Y, Pts[6].Z); glVertex3f(Pts[7].X, Pts[7].Y, Pts[7].Z);
|
||||
{ ┬хЁїэ }
|
||||
glColor3f(R * 0.9, G * 0.9, B * 0.9);
|
||||
glVertex3f(Pts[5].X, Pts[5].Y, Pts[5].Z); glVertex3f(Pts[3].X, Pts[3].Y, Pts[3].Z);
|
||||
glVertex3f(Pts[2].X, Pts[2].Y, Pts[2].Z); glVertex3f(Pts[6].X, Pts[6].Y, Pts[6].Z);
|
||||
{ ═шцэ }
|
||||
glColor3f(R * 0.3, G * 0.3, B * 0.3);
|
||||
glVertex3f(Pts[4].X, Pts[4].Y, Pts[4].Z); glVertex3f(Pts[7].X, Pts[7].Y, Pts[7].Z);
|
||||
glVertex3f(Pts[1].X, Pts[1].Y, Pts[1].Z); glVertex3f(Pts[0].X, Pts[0].Y, Pts[0].Z);
|
||||
{ ╧Ёртр }
|
||||
glColor3f(R * 0.8, G * 0.8, B * 0.8);
|
||||
glVertex3f(Pts[7].X, Pts[7].Y, Pts[7].Z); glVertex3f(Pts[6].X, Pts[6].Y, Pts[6].Z);
|
||||
glVertex3f(Pts[2].X, Pts[2].Y, Pts[2].Z); glVertex3f(Pts[1].X, Pts[1].Y, Pts[1].Z);
|
||||
{ ╦хтр }
|
||||
glColor3f(R * 0.6, G * 0.6, B * 0.6);
|
||||
glVertex3f(Pts[4].X, Pts[4].Y, Pts[4].Z); glVertex3f(Pts[0].X, Pts[0].Y, Pts[0].Z);
|
||||
glVertex3f(Pts[3].X, Pts[3].Y, Pts[3].Z); glVertex3f(Pts[5].X, Pts[5].Y, Pts[5].Z);
|
||||
glEnd();
|
||||
end;
|
||||
|
||||
procedure UpdateRubikLogic;
|
||||
begin
|
||||
LayerAngle := LayerAngle + 3.0;
|
||||
if LayerAngle >= 90.0 then
|
||||
begin
|
||||
LayerAngle := 0;
|
||||
Inc(ActiveLayer);
|
||||
if ActiveLayer > 1 then
|
||||
begin
|
||||
ActiveLayer := -1;
|
||||
ActiveAxis := (ActiveAxis + 1) mod 3;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure GLDraw;
|
||||
var
|
||||
ThreadInfo: TThreadInfo;
|
||||
X, Y, Z: Integer;
|
||||
R_Clr, G_Clr, B_Clr: GLFloat;
|
||||
begin
|
||||
GetThreadInfo($FFFFFFFF, ThreadInfo);
|
||||
if ThreadInfo.Client.Height <= 3 then Exit;
|
||||
|
||||
kosglMakeCurrent(0, 0, ThreadInfo.Client.Width, ThreadInfo.Client.Height, CTX);
|
||||
glViewPort(0, 0, ThreadInfo.Client.Width, ThreadInfo.Client.Height);
|
||||
|
||||
glClearColor(0.03, 0.03, 0.06, 0.0);
|
||||
glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glEnable(GL_CULL_FACE);
|
||||
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glLoadIdentity();
|
||||
Perspective(45.0, ThreadInfo.Client.Width / ThreadInfo.Client.Height, 0.1, 100.0);
|
||||
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glLoadIdentity();
|
||||
|
||||
// ╠╚╨╬┬█┼ ╥╨└═╤╘╬╨╠└╓╚╚ (┬Ёр∙хэшх ърьхЁ√ тюъЁєу тёхщ ёЎхэ√)
|
||||
glTranslatef(0.0, 0.0, ZTr);
|
||||
glRotatef(25.0 + Rotation * 0.4, 1.0, 0.0, 0.0);
|
||||
glRotatef(35.0 + Rotation, 0.0, 1.0, 0.0);
|
||||
|
||||
// ╤┴╬╨╩└ ╚ ╬╥╨╚╤╬┬╩└ ╤┼╥╩╚
|
||||
for X := -1 to 1 do
|
||||
for Y := -1 to 1 do
|
||||
for Z := -1 to 1 do
|
||||
begin
|
||||
// ярышЄЁр эр ёшэєёрї юЄ тЁхьхэш
|
||||
R_Clr := 0.7 + Sin(TimeVal + X * 0.5) * 0.3;
|
||||
G_Clr := 0.7 + Cos(TimeVal * 0.8 + Y * 0.5) * 0.3;
|
||||
B_Clr := 0.7 + Sin(TimeVal * 1.2 + Z * 0.5) * 0.3;
|
||||
|
||||
DrawSubCube(0.26, X, Y, Z, R_Clr, G_Clr, B_Clr);
|
||||
end;
|
||||
|
||||
kosglSwapBuffers();
|
||||
|
||||
UpdateRubikLogic;
|
||||
Rotation := Rotation + CamSpeed;
|
||||
TimeVal := TimeVal + 0.03;
|
||||
end;
|
||||
|
||||
begin
|
||||
TinyGL_initialization;
|
||||
|
||||
with GetScreenSize do
|
||||
begin
|
||||
WndWidth := Width div 3 * 2;
|
||||
WndHeight := Height div 3 * 2;
|
||||
WndLeft := (Width - WndWidth) div 2;
|
||||
WndTop := (Height - WndHeight) div 2;
|
||||
end;
|
||||
|
||||
while True do
|
||||
case WaitEventByTime(1) of
|
||||
REDRAW_EVENT:
|
||||
begin
|
||||
BeginDraw;
|
||||
DrawWindow(WndLeft, WndTop, WndWidth, WndHeight, '3D Rubik Rotate', $00FFFFFF,
|
||||
WS_SKINNED_SIZABLE + WS_CLIENT_COORDS + WS_CAPTION, CAPTION_MOVABLE);
|
||||
GLDraw;
|
||||
EndDraw;
|
||||
end;
|
||||
KEY_EVENT: GetKey;
|
||||
BUTTON_EVENT: if GetButton.ID = 1 then ExitThread;
|
||||
else
|
||||
GLDraw;
|
||||
end;
|
||||
end.
|
||||
@@ -1,193 +0,0 @@
|
||||
program SierpinskiTinyGL;
|
||||
|
||||
uses
|
||||
KolibriOS, TinyGL;
|
||||
|
||||
|
||||
type
|
||||
Point3D = record
|
||||
X, Y, Z: GLFloat;
|
||||
end;
|
||||
|
||||
const
|
||||
{ ╩ююЁфшэрЄ√ срчютюую ЄхЄЁр¤фЁр }
|
||||
TopV: Point3D = (X: 0.0; Y: -1.0; Z: 0.0);
|
||||
LeftV: Point3D = (X: -1.0; Y: 0.7; Z: -0.5);
|
||||
RightV: Point3D = (X: 1.0; Y: 0.7; Z: -0.5);
|
||||
BackV: Point3D = (X: 0.0; Y: 0.7; Z: 1.0);
|
||||
|
||||
var
|
||||
AngleX: GLFloat = 0.5;
|
||||
AngleY: GLFloat = 0.5;
|
||||
TimeColor: GLFloat = 0.0;
|
||||
TimeDepth: GLFloat = 0.0;
|
||||
CTX: TKOSGLContext;
|
||||
|
||||
WndLeft, WndTop, WndWidth, WndHeight: LongInt;
|
||||
|
||||
IsLine: Boolean;
|
||||
|
||||
{ ═рёЄЁющър яхЁёяхъЄшт√ ърьхЁ√ }
|
||||
procedure Perspective(fovY, Aspect, zNear, zFar: GLDouble);
|
||||
var
|
||||
fW, fH, fovYPI360: GLDouble;
|
||||
M: array[0..15] of GLFloat;
|
||||
begin
|
||||
FillChar(M, SizeOf(M), #0);
|
||||
fovYPI360 := fovY * PI / 360;
|
||||
fH := Sin(fovYPI360) * zNear / Cos(fovYPI360);
|
||||
fW := fH * Aspect;
|
||||
M[0] := zNear / fW;
|
||||
M[5] := zNear / fH;
|
||||
M[10] := -(zFar + zNear) / (zFar - zNear);
|
||||
M[11] := -1;
|
||||
M[14] := -2 * zFar * zNear / (zFar - zNear);
|
||||
glLoadMatrixf(@M[0]);
|
||||
end;
|
||||
|
||||
function Midpoint(P1, P2: Point3D): Point3D;
|
||||
begin
|
||||
Result.X := (P1.X + P2.X) / 2;
|
||||
Result.Y := (P1.Y + P2.Y) / 2;
|
||||
Result.Z := (P1.Z + P2.Z) / 2;
|
||||
end;
|
||||
|
||||
{ т√ўшёы хЄ цшфъшщ уЁрфшхэЄэ√щ ЎтхЄ яю ъююЁфшэрЄрь Єюўъш
|
||||
ш яхЁхфр╕Є тхЁ°шэє т TinyGL }
|
||||
procedure GlColorVertex(P: Point3D);
|
||||
var
|
||||
R, G, B: GLFloat;
|
||||
begin
|
||||
{ ╞шфъшщ уЁрфшхэЄ}
|
||||
R := sin(P.X * 2 + TimeColor) * 0.5 + 0.5;
|
||||
G := sin(P.Y * 2 + TimeColor * 1.5) * 0.5 + 0.5;
|
||||
B := cos(P.Z * 2 + TimeColor) * 0.5 + 0.5;
|
||||
|
||||
if not IsLine then
|
||||
glColor3f(R, G, B)
|
||||
else
|
||||
glColor3f(1 - R * 0.25, 1 - G * 0.25, 1 - B * 0.25);
|
||||
|
||||
glVertex3f(P.X, P.Y, P.Z);
|
||||
end;
|
||||
|
||||
procedure DrawTetrahedron(P1, P2, P3, P4: Point3D);
|
||||
begin
|
||||
GlColorVertex(P1); GlColorVertex(P2); GlColorVertex(P3);
|
||||
GlColorVertex(P1); GlColorVertex(P3); GlColorVertex(P4);
|
||||
GlColorVertex(P1); GlColorVertex(P4); GlColorVertex(P2);
|
||||
GlColorVertex(P2); GlColorVertex(P3); GlColorVertex(P4);
|
||||
end;
|
||||
|
||||
procedure Sierpinski3D(P1, P2, P3, P4: Point3D; Depth: Integer);
|
||||
var
|
||||
M12, M23, M31, M14, M24, M34: Point3D;
|
||||
begin
|
||||
if Depth = 0 then
|
||||
DrawTetrahedron(P1, P2, P3, P4)
|
||||
else
|
||||
begin
|
||||
M12 := Midpoint(P1, P2);
|
||||
M23 := Midpoint(P2, P3);
|
||||
M31 := Midpoint(P3, P1);
|
||||
M14 := Midpoint(P1, P4);
|
||||
M24 := Midpoint(P2, P4);
|
||||
M34 := Midpoint(P3, P4);
|
||||
|
||||
Sierpinski3D(P1, M12, M31, M14, Depth - 1);
|
||||
Sierpinski3D(M12, P2, M23, M24, Depth - 1);
|
||||
Sierpinski3D(M31, M23, P3, M34, Depth - 1);
|
||||
Sierpinski3D(M14, M24, M34, P4, Depth - 1);
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure GLDraw;
|
||||
var
|
||||
ThreadInfo: TThreadInfo;
|
||||
CurrentDepth: Integer;
|
||||
begin
|
||||
GetThreadInfo($FFFFFFFF, ThreadInfo);
|
||||
if ThreadInfo.Client.Height <= 3 then Exit;
|
||||
|
||||
kosglMakeCurrent(0, 0, ThreadInfo.Client.Width, ThreadInfo.Client.Height, CTX);
|
||||
glViewPort(0, 0, ThreadInfo.Client.Width, ThreadInfo.Client.Height);
|
||||
|
||||
glClearColor(0.0, 0.0, 0.0, 1.0);
|
||||
glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glLoadIdentity();
|
||||
Perspective(45.0, ThreadInfo.Client.Width / ThreadInfo.Client.Height, 0.1, 100.0);
|
||||
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glLoadIdentity();
|
||||
|
||||
{ ╩рьхЁр }
|
||||
glTranslatef(0.0, 0.0, -3.5);
|
||||
|
||||
{ ┬Ёр∙хэшх }
|
||||
glRotatef(AngleX * (180 / PI), 1.0, 0.0, 0.0);
|
||||
glRotatef(AngleY * (180 / PI), 0.0, 1.0, 0.0);
|
||||
|
||||
{ ╚чьхэхэшх уыєсшэ√ ЇЁръЄрыр }
|
||||
CurrentDepth := Trunc(2.5 + Sin(TimeDepth) * 1.6);
|
||||
if CurrentDepth < 1 then CurrentDepth := 1;
|
||||
if CurrentDepth > 4 then CurrentDepth := 4;
|
||||
|
||||
{ Ёшёєхь ё чрыштъющ }
|
||||
IsLine := False;
|
||||
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
||||
glBegin(GL_TRIANGLES);
|
||||
Sierpinski3D(TopV, LeftV, RightV, BackV, CurrentDepth);
|
||||
glEnd();
|
||||
|
||||
{ Ёшёєхь ъюэЄєЁэ√х ышэшш }
|
||||
IsLine := True;
|
||||
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
|
||||
glBegin(GL_TRIANGLES);
|
||||
Sierpinski3D(TopV, LeftV, RightV, BackV, CurrentDepth);
|
||||
glEnd();
|
||||
|
||||
kosglSwapBuffers();
|
||||
|
||||
{ ╬сэютыхэшх єуыют }
|
||||
AngleX := AngleX + 0.003;
|
||||
AngleY := AngleY + 0.007;
|
||||
|
||||
TimeColor := TimeColor + 0.02;
|
||||
TimeDepth := TimeDepth + 0.008;
|
||||
end;
|
||||
|
||||
begin
|
||||
TinyGL_initialization;
|
||||
|
||||
with GetScreenSize do
|
||||
begin
|
||||
WndWidth := Width div 3 * 2;
|
||||
WndHeight := Height div 3 * 2;
|
||||
WndLeft := (Width - WndWidth) div 2;
|
||||
WndTop := (Height - WndHeight) div 2;
|
||||
end;
|
||||
|
||||
while True do
|
||||
case WaitEventByTime(1) of
|
||||
REDRAW_EVENT:
|
||||
begin
|
||||
BeginDraw;
|
||||
DrawWindow(WndLeft, WndTop, WndWidth, WndHeight,
|
||||
'Sierpinski 3D', $00000000,
|
||||
WS_SKINNED_SIZABLE + WS_CLIENT_COORDS + WS_CAPTION,
|
||||
CAPTION_MOVABLE);
|
||||
GLDraw;
|
||||
EndDraw;
|
||||
end;
|
||||
KEY_EVENT:
|
||||
GetKey;
|
||||
BUTTON_EVENT:
|
||||
if GetButton.ID = 1 then
|
||||
ExitThread;
|
||||
else
|
||||
GLDraw;
|
||||
end;
|
||||
end.
|
||||
Loaded 100 of 313 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user