aboutsummaryrefslogtreecommitdiff
path: root/dostsr.h
diff options
context:
space:
mode:
authorJavier <dev.git@javispedro.com>2022-04-11 04:36:49 +0200
committerJavier <dev.git@javispedro.com>2022-04-11 04:36:49 +0200
commit19231982b2f374aed286f4697aebd3fb9fda05d8 (patch)
tree1922eaf34af3d904ce0f75c0e812e8da8e0d38d4 /dostsr.h
parent970f90228a6978712c28529437721caffec76202 (diff)
downloadvbados-19231982b2f374aed286f4697aebd3fb9fda05d8.tar.gz
vbados-19231982b2f374aed286f4697aebd3fb9fda05d8.zip
add new virtualbox shared folders client
Diffstat (limited to 'dostsr.h')
-rw-r--r--dostsr.h116
1 files changed, 116 insertions, 0 deletions
diff --git a/dostsr.h b/dostsr.h
new file mode 100644
index 0000000..726ef3a
--- /dev/null
+++ b/dostsr.h
@@ -0,0 +1,116 @@
+/*
+ * VBMouse - utility functions for DOS TSRs
+ * Copyright (C) 2022 Javier S. Pedro
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#ifndef DOSTSR_H
+#define DOSTSR_H
+
+#include <stdint.h>
+
+#include "int21dos.h"
+
+/** Deallocates the environment block from the passed PSP segment. */
+static void deallocate_environment(segment_t psp)
+{
+ // TODO : Too lazy to make PSP struct;
+ // 0x2C is offsetof the environment block field on the PSP
+ uint16_t __far *envblockP = (uint16_t __far *) MK_FP(psp, 0x2C);
+ dos_free(*envblockP);
+ *envblockP = 0;
+}
+
+/** Copies a program to another location.
+ * @param new_seg PSP segment for the new location
+ * @param old_seg PSP segment for the old location
+ * @param size size of the program to copy including PSP size. */
+static void copy_program(segment_t new_seg, segment_t old_seg, unsigned size)
+{
+ // The MCB is always 1 segment before.
+ uint8_t __far *new_mcb = MK_FP(new_seg - 1, 0);
+ uint8_t __far *old_mcb = MK_FP(old_seg - 1, 0);
+ uint16_t __far *new_mcb_owner = (uint16_t __far *) &new_mcb[1];
+ char __far *new_mcb_owner_name = &new_mcb[8];
+ char __far *old_mcb_owner_name = &old_mcb[8];
+
+ // Copy entire resident segment including PSP
+ _fmemcpy(MK_FP(new_seg, 0), MK_FP(old_seg, 0), size);
+
+ // Make the new MCB point to itself as owner
+ *new_mcb_owner = new_seg;
+
+ // Copy the program name, too.
+ _fmemcpy(new_mcb_owner_name, old_mcb_owner_name, 8);
+}
+
+/** Allocates a UMB of the given size.
+ * If no UMBs are available, this may still return a block in conventional memory. */
+static __segment allocate_umb(unsigned size)
+{
+ bool old_umb_link = dos_query_umb_link_state();
+ unsigned int old_strategy = dos_query_allocation_strategy();
+ segment_t new_segment;
+
+ dos_set_umb_link_state(true);
+ dos_set_allocation_strategy(DOS_FIT_BEST | DOS_FIT_HIGHONLY);
+
+ new_segment = dos_alloc(get_paragraphs(size));
+
+ dos_set_umb_link_state(old_umb_link);
+ dos_set_allocation_strategy(old_strategy);
+
+ return new_segment;
+}
+
+static __segment reallocate_to_umb(segment_t __far * cur_seg, unsigned segment_size)
+{
+ segment_t old_psp_segment = *cur_seg - (DOS_PSP_SIZE/16);
+ segment_t new_psp_segment;
+
+ deallocate_environment(_psp);
+
+ // If we are already in UMA, don't bother
+ if (old_psp_segment >= 0xA000) {
+ return 0;
+ }
+
+ new_psp_segment = allocate_umb(segment_size);
+
+ if (new_psp_segment && new_psp_segment >= 0xA000) {
+ segment_t new_segment = new_psp_segment + (DOS_PSP_SIZE/16);
+ printf("Moving to upper memory\n");
+
+ // Create a new program instance including PSP at the new_segment
+ copy_program(new_psp_segment, old_psp_segment, segment_size);
+
+ // Tell DOS to "switch" to the new program
+ dos_set_psp(new_psp_segment);
+
+ // Return the new segment
+ return new_segment;
+ } else {
+ printf("No upper memory available\n");
+ if (new_psp_segment) {
+ // In case we got another low-memory segment...
+ dos_free(new_psp_segment);
+ }
+
+ return 0;
+ }
+}
+
+#endif // DOSTSR_H