mirror of
https://github.com/wwarthen/RomWBW.git
synced 2026-02-06 22:43:15 -06:00
Compare commits
31 Commits
v3.4.0-dev
...
v3.4.0-dev
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
214182b514 | ||
|
|
08942fb944 | ||
|
|
5dc724785b | ||
|
|
ce17be9ba6 | ||
|
|
badca621ba | ||
|
|
291cdd2c03 | ||
|
|
888d9879c9 | ||
|
|
39446d5e4f | ||
|
|
af8385fba8 | ||
|
|
10ff97b6c6 | ||
|
|
7e9191f3ef | ||
|
|
a67b1ecd0a | ||
|
|
4012ee7775 | ||
|
|
150ca6b50c | ||
|
|
6af84e9ad8 | ||
|
|
6bcad122cd | ||
|
|
003481410f | ||
|
|
9a1c3f7929 | ||
|
|
ef536750ea | ||
|
|
347a15a3b6 | ||
|
|
1e5b38c251 | ||
|
|
29f93fb153 | ||
|
|
b0975745df | ||
|
|
163460856a | ||
|
|
3ce9246904 | ||
|
|
1a021e02b9 | ||
|
|
f2d304ef0d | ||
|
|
cbfbca8d92 | ||
|
|
b175808a92 | ||
|
|
3e86e79133 | ||
|
|
3247e67ed4 |
4
.github/workflows/commit.yml
vendored
4
.github/workflows/commit.yml
vendored
@@ -26,7 +26,7 @@ jobs:
|
||||
run: |
|
||||
export TZ='America/Los_Angeles'
|
||||
sudo apt-get install srecord
|
||||
make dist
|
||||
make distlog
|
||||
rm -rf .git*
|
||||
|
||||
- name: List Output
|
||||
@@ -58,7 +58,7 @@ jobs:
|
||||
run: |
|
||||
export TZ='America/Los_Angeles'
|
||||
brew install srecord
|
||||
make dist
|
||||
make distlog
|
||||
rm -rf .git*
|
||||
|
||||
- name: List Output
|
||||
|
||||
2
.github/workflows/release.yml
vendored
2
.github/workflows/release.yml
vendored
@@ -19,7 +19,7 @@ jobs:
|
||||
export TZ='America/Los_Angeles'
|
||||
sudo apt-get install libncurses-dev
|
||||
sudo apt-get install srecord
|
||||
make dist
|
||||
make distlog
|
||||
rm -rf .git*
|
||||
|
||||
- name: Create Package Archive
|
||||
|
||||
4
.gitignore
vendored
4
.gitignore
vendored
@@ -95,8 +95,8 @@ Tools/unix/zx/zx
|
||||
!Source/ZPM3/*.[Cc][Oo][Mm]
|
||||
!Source/ZSDOS/*.[Cc][Oo][Mm]
|
||||
!Source/ZRC/*.bin
|
||||
!Source/ZZRC/*.bin
|
||||
!Source/ZZRC/*.hex
|
||||
!Source/Z1RCC/*.bin
|
||||
!Source/ZZRCC/*.bin
|
||||
!Tools/cpm/**
|
||||
!Tools/unix/zx/*
|
||||
!Tools/zx/*
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
10
Makefile
10
Makefile
@@ -1,5 +1,8 @@
|
||||
.PHONY: tools source clean clobber diff dist
|
||||
|
||||
.ONESHELL:
|
||||
.SHELLFLAGS = -cex
|
||||
|
||||
all: tools source
|
||||
|
||||
tools:
|
||||
@@ -20,6 +23,9 @@ diff:
|
||||
$(MAKE) --directory Source diff
|
||||
|
||||
dist:
|
||||
$(MAKE) ROM_PLATFORM=dist 2>&1 | tee make.log
|
||||
$(MAKE) --directory Source clean
|
||||
$(MAKE) ROM_PLATFORM=dist
|
||||
$(MAKE) --directory Tools clean
|
||||
$(MAKE) --directory Source clean
|
||||
|
||||
distlog:
|
||||
$(MAKE) dist 2>&1 | tee make.log
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
**RomWBW ReadMe** \
|
||||
Version 3.4 \
|
||||
Wayne Warthen ([wwarthen@gmail.com](mailto:wwarthen@gmail.com)) \
|
||||
09 Oct 2023
|
||||
31 Oct 2023
|
||||
|
||||
# Overview
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
RomWBW ReadMe
|
||||
Wayne Warthen (wwarthen@gmail.com)
|
||||
09 Oct 2023
|
||||
31 Oct 2023
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -7,20 +7,24 @@
|
||||
; keyboard, and mouse.
|
||||
;
|
||||
; WBW 2022-03-28: Add menu driven port selection
|
||||
; Add support for RHYOPHYRE
|
||||
; Add support for Rhyophyre
|
||||
; WBW 2022-04-01: Add menu for test functions
|
||||
; WBW 2022-04-02: Fix prtchr register saving/recovery
|
||||
; WBW 2023-10-19: Add support for Duodyne
|
||||
;
|
||||
;=======================================================================
|
||||
;
|
||||
; PS/2 Keyboard/Mouse controller port addresses (adjust as needed)
|
||||
;
|
||||
; MBC:
|
||||
; Nhyodyne:
|
||||
iocmd_mbc .equ $E3 ; PS/2 controller command port address
|
||||
iodat_mbc .equ $E2 ; PS/2 controller data port address
|
||||
; RPH:
|
||||
; Rhyophyre:
|
||||
iocmd_rph .equ $8D ; PS/2 controller command port address
|
||||
iodat_rph .equ $8C ; PS/2 controller data port address
|
||||
; Duodyne:
|
||||
iocmd_duo .equ $4D ; PS/2 controller command port address
|
||||
iodat_duo .equ $4C ; PS/2 controller data port address
|
||||
;
|
||||
cpumhz .equ 8 ; for time delay calculations (not critical)
|
||||
;
|
||||
@@ -77,10 +81,12 @@ setup1:
|
||||
jr z,setup1
|
||||
call upcase
|
||||
call prtchr
|
||||
cp '1' ; MBC
|
||||
cp '1' ; Nhyodyne
|
||||
jr z,setup_mbc
|
||||
cp '2' ; RHYOPHYRE
|
||||
cp '2' ; Rhyophyre
|
||||
jr z,setup_rph
|
||||
cp '3' ; Duodyne
|
||||
jr z,setup_duo
|
||||
cp 'X'
|
||||
jr z,exit
|
||||
jr setup
|
||||
@@ -101,6 +107,14 @@ setup_rph:
|
||||
ld de,str_rph
|
||||
jr setup2
|
||||
;
|
||||
setup_duo:
|
||||
ld a,iocmd_duo
|
||||
ld (iocmd),a
|
||||
ld a,iodat_duo
|
||||
ld (iodat),a
|
||||
ld de,str_duo
|
||||
jr setup2
|
||||
;
|
||||
setup2:
|
||||
call prtstr
|
||||
call crlf2
|
||||
@@ -181,6 +195,12 @@ test_kbd:
|
||||
;
|
||||
call ctlr_test
|
||||
jr nz,test_kbd_fail
|
||||
;
|
||||
ld a,$20 ; kbd enabled, mse disabled, no ints
|
||||
call ctlr_setup
|
||||
jr nz,test_kbd_fail
|
||||
;
|
||||
call ctlr_flush
|
||||
;
|
||||
call test_kbd_basic
|
||||
jr nz,test_kbd_fail
|
||||
@@ -228,9 +248,13 @@ test_mse:
|
||||
ld a,$10 ; kbd disabled, mse enabled, no ints
|
||||
call ctlr_setup
|
||||
jr nz,test_mse_fail
|
||||
;
|
||||
call ctlr_flush
|
||||
;
|
||||
call mse_reset
|
||||
jr nz,test_mse_fail
|
||||
;
|
||||
call ctlr_flush
|
||||
;
|
||||
call mse_ident
|
||||
jr nz,test_mse_fail
|
||||
@@ -262,15 +286,21 @@ test_kbdmse:
|
||||
ld a,$00 ; kbd enabled, mse enabled, no ints
|
||||
call ctlr_setup
|
||||
jr nz,test_kbdmse_fail
|
||||
;
|
||||
call ctlr_flush
|
||||
;
|
||||
call kbd_reset
|
||||
jr nz,test_kbdmse_fail
|
||||
;
|
||||
call ctlr_flush
|
||||
;
|
||||
ld a,2
|
||||
call kbd_setsc
|
||||
;
|
||||
call mse_reset
|
||||
jr nz,test_kbdmse_fail
|
||||
;
|
||||
call ctlr_flush
|
||||
;
|
||||
call mse_stream
|
||||
jr nz,test_kbdmse_fail
|
||||
@@ -290,15 +320,13 @@ test_kbdmse_fail:
|
||||
; inventory the supported scan code sets.
|
||||
;
|
||||
test_kbd_basic:
|
||||
ld a,$20 ; Xlat off for this checking
|
||||
call ctlr_setup
|
||||
ret nz
|
||||
;
|
||||
call kbd_reset
|
||||
ret nz
|
||||
;
|
||||
call ctlr_flush
|
||||
;
|
||||
call kbd_ident
|
||||
;ret nz
|
||||
ret nz
|
||||
;
|
||||
ld b,3 ; Loop control, 3 scan code sets
|
||||
ld c,1 ; Current scan code number
|
||||
@@ -436,6 +464,19 @@ ctlr_setup:
|
||||
xor a
|
||||
ret
|
||||
;
|
||||
; Flush incoming data buffer
|
||||
;
|
||||
ctlr_flush:
|
||||
call crlf2
|
||||
ld de,str_ctlr_flush
|
||||
call prtstr
|
||||
ctlr_flush1:
|
||||
call delay ; small delay
|
||||
call check_read ; data pending?
|
||||
ret nz ; return if nothing there
|
||||
call get_data_dbg ; get and discard byte
|
||||
jr ctlr_flush1 ; loop
|
||||
;
|
||||
; Perform a keyboard reset
|
||||
;
|
||||
kbd_reset:
|
||||
@@ -612,13 +653,17 @@ mse_reset:
|
||||
call crlf2
|
||||
ld de,str_mse_reset
|
||||
call prtstr
|
||||
ld a,$f2 ; Identify mouse command
|
||||
ld a,$ff ; Identify mouse command
|
||||
call put_data_mse_dbg
|
||||
jp c,err_ctlr_to ; handle controller error
|
||||
call get_data_dbg
|
||||
jp c,err_ctlr_to ; handle controller error
|
||||
cp $fa ; Is it an ack as expected?
|
||||
jp nz,err_mse_reset
|
||||
call get_data_dbg
|
||||
jp c,err_ctlr_to ; handle controller error
|
||||
cp $aa ; Success?
|
||||
jp nz,err_mse_reset
|
||||
call crlf
|
||||
ld de,str_mse_reset_ok
|
||||
call prtstr
|
||||
@@ -634,18 +679,61 @@ mse_ident:
|
||||
ld a,$f2 ; Identify mouse command
|
||||
call put_data_mse_dbg
|
||||
jp c,err_ctlr_to ; handle controller error
|
||||
mse_ident0:
|
||||
call get_data_dbg
|
||||
jp c,err_ctlr_to ; handle controller error
|
||||
|
||||
;cp $00 ; extraneous?
|
||||
;jr z,mse_ident0 ; ignore it, get another
|
||||
|
||||
cp $fa ; Is it an ack as expected?
|
||||
jp nz,err_mse_ident
|
||||
call get_data_dbg
|
||||
jp c,err_ctlr_to ; handle controller error
|
||||
; Now we need to receive 0-2 bytes. There is no way to know
|
||||
; how many are coming, so we receive bytes until there is a
|
||||
; timeout error. Timeout is shortened here so that we don't
|
||||
; have to wait seconds for the routine to complete normally.
|
||||
; A short timeout is more than sufficient here.
|
||||
ld ix,workbuf
|
||||
ld a,(timeout) ; save current timeout
|
||||
push af
|
||||
ld a,stimout ; set a short timeout
|
||||
ld (timeout),a
|
||||
ld b,8 ; buf max
|
||||
ld c,0 ; buf len
|
||||
mse_ident1:
|
||||
push bc
|
||||
call get_data_dbg
|
||||
pop bc
|
||||
jr c,mse_ident2
|
||||
ld (ix),a
|
||||
inc ix
|
||||
inc c
|
||||
djnz mse_ident1
|
||||
mse_ident2:
|
||||
pop af ; restore original timeout
|
||||
ld (timeout),a
|
||||
call crlf
|
||||
ld de,str_mse_ident_disp
|
||||
call prtstr
|
||||
pop af
|
||||
call prtdecb
|
||||
ld a,'['
|
||||
call prtchr
|
||||
ld ix,workbuf
|
||||
ld a,c ; bytes to print
|
||||
or a ; check for zero
|
||||
jr z,mse_ident4 ; handle zero
|
||||
ld b,a ; setup loop counter
|
||||
jr mse_ident3a
|
||||
mse_ident3:
|
||||
ld a,','
|
||||
call prtchr
|
||||
mse_ident3a:
|
||||
ld a,(ix)
|
||||
call prthex
|
||||
inc ix
|
||||
djnz mse_ident3
|
||||
mse_ident4:
|
||||
ld a,']'
|
||||
call prtchr
|
||||
xor a
|
||||
ret
|
||||
;
|
||||
@@ -658,8 +746,13 @@ mse_stream:
|
||||
ld a,$f4 ; Stream packets cmd
|
||||
call put_data_mse_dbg
|
||||
jp c,err_ctlr_to ; handle controller error
|
||||
mse_stream0:
|
||||
call get_data_dbg
|
||||
jp c,err_ctlr_to ; handle controller error
|
||||
|
||||
;cp $00 ; extraneous?
|
||||
;jr z,mse_stream0 ; ignore it, get another
|
||||
|
||||
cp $FA ; Is it an ack as expected?
|
||||
jp nz,err_mse_stream
|
||||
xor a
|
||||
@@ -1344,14 +1437,16 @@ delay1:
|
||||
; Constants
|
||||
;=======================================================================
|
||||
;
|
||||
str_banner .db "PS/2 Keyboard/Mouse Information v0.6a, 2-Apr-2022",0
|
||||
str_banner .db "PS/2 Keyboard/Mouse Information v0.8, 6-Nov-2023",0
|
||||
str_hwmenu .db "PS/2 Controller Port Options:\r\n\r\n"
|
||||
.db " 1 - MBC\r\n"
|
||||
.db " 2 - RHYOPHYRE\r\n"
|
||||
.db " 1 - Nhyodyne\r\n"
|
||||
.db " 2 - Rhyophyre\r\n"
|
||||
.db " 3 - Duodyne\r\n"
|
||||
.db " X - Exit Application\r\n"
|
||||
.db "\r\nSelection? ",0
|
||||
str_mbc .db "MBC",0
|
||||
str_rph .db "RHYOPHYRE",0
|
||||
str_mbc .db "Nhyodyne",0
|
||||
str_rph .db "Rhyophyre",0
|
||||
str_duo .db "Duodyne",0
|
||||
str_menu .db "PS/2 Testing Options:\r\n\r\n"
|
||||
.db " C - Test PS/2 Controller\r\n"
|
||||
.db " K - Test PS/2 Keyboard\r\n"
|
||||
@@ -1382,6 +1477,7 @@ str_trans_off .db "***** Testing Keyboard with Scan Code Translation DISABLED *
|
||||
str_trans_on .db "***** Testing Keyboard with Scan Code Translation ENABLED *****",0
|
||||
str_basic_mse .db "***** Basic Mouse Tests *****",0
|
||||
str_kbdmse .db "***** Test All Devices Combined *****",0
|
||||
str_ctlr_flush .db "Flushing controller input buffer",0
|
||||
str_kbd_reset .db "Attempting Keyboard Reset",0
|
||||
str_kbd_reset_ok .db "Keyboard Reset OK",0
|
||||
str_err_kbd_reset .db "Keyboard Reset Failed",0
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
; Use CPM3 BDOS direct BIOS call to get DRVTBL adr
|
||||
; 2023-06-19 [WBW] Update for revised DIODEVICE API
|
||||
; 2023-09-19 [WBW] Added CHUSB & CHSD device support
|
||||
; 2023-10-13 [WBW] Fixed DPH creation to select correct DPB
|
||||
;_______________________________________________________________________________
|
||||
;
|
||||
; ToDo:
|
||||
@@ -665,10 +666,10 @@ makdphwbw: ; determine appropriate dpb (WBW mode, unit number in A)
|
||||
jr makdph0 ; jump ahead
|
||||
makdph00:
|
||||
ld e,6 ; assume floppy
|
||||
cp $10 ; floppy?
|
||||
cp $01 ; floppy?
|
||||
jr z,makdph0 ; yes, jump ahead
|
||||
ld e,3 ; assume ram floppy
|
||||
cp $20 ; ram floppy?
|
||||
cp $02 ; ram floppy?
|
||||
jr z,makdph0 ; yes, jump ahead
|
||||
ld e,4 ; everything else is assumed to be hard disk
|
||||
jr makdph0 ; yes, jump ahead
|
||||
@@ -1935,13 +1936,13 @@ stack .equ $ ; stack top
|
||||
; Messages
|
||||
;
|
||||
indent .db " ",0
|
||||
msgban1 .db "ASSIGN v1.7 for RomWBW CP/M ",0
|
||||
msgban1 .db "ASSIGN v1.8 for RomWBW CP/M ",0
|
||||
msg22 .db "2.2",0
|
||||
msg3 .db "3",0
|
||||
msbban2 .db ", 19-Sep-2023",0
|
||||
msbban2 .db ", 13-Oct-2023",0
|
||||
msghb .db " (HBIOS Mode)",0
|
||||
msgub .db " (UBIOS Mode)",0
|
||||
msgban3 .db "Copyright 2021, Wayne Warthen, GNU GPL v3",0
|
||||
msgban3 .db "Copyright 2023, Wayne Warthen, GNU GPL v3",0
|
||||
msguse .db "Usage: ASSIGN D:[=[{D:|<device>[<unitnum>]:[<slicenum>]}]][,...]",13,10
|
||||
.db " ex. ASSIGN (display all active assignments)",13,10
|
||||
.db " ASSIGN /? (display version and usage)",13,10
|
||||
|
||||
@@ -8,6 +8,7 @@ call BuildShared || exit /b
|
||||
call BuildImages || exit /b
|
||||
call BuildROM %* || exit /b
|
||||
call BuildZRC || exit /b
|
||||
call BuildZ1RCC || exit /b
|
||||
call BuildZZRCC || exit /b
|
||||
|
||||
if "%1" == "dist" (
|
||||
|
||||
4
Source/BuildZ1RCC.cmd
Normal file
4
Source/BuildZ1RCC.cmd
Normal file
@@ -0,0 +1,4 @@
|
||||
@echo off
|
||||
setlocal
|
||||
|
||||
pushd Z1RCC && call Build || exit /b & popd
|
||||
@@ -346,8 +346,7 @@ read:
|
||||
ld b,17h ; HBIOS DEVICE function
|
||||
rst 08 ; Do it, D=device type
|
||||
ld a,d ; put in accum
|
||||
and 0F0h ; isolate high bits
|
||||
cp 10h ; floppy?
|
||||
cp 01h ; floppy?
|
||||
jr nz,read2 ; if not, do LBA i/o
|
||||
|
||||
; Floppy I/O
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
extrn @dtbl,@ctbl
|
||||
extrn @date,@hour,@min,@sec
|
||||
extrn @srch1
|
||||
extrn @hbbio
|
||||
extrn @hbbio,@hbusr
|
||||
extrn addhla
|
||||
extrn phex16, phex8
|
||||
extrn cin, cout
|
||||
@@ -46,7 +46,7 @@ tpa$bank equ 0
|
||||
; Clone page zero from bank 0 to additional banks
|
||||
ld b,2 ; last bank
|
||||
ld c,0 ; src bank
|
||||
init$2:
|
||||
init$1:
|
||||
push bc ; save bank id's
|
||||
call ?xmove ; set src/dest banks
|
||||
ld bc,0100h ; size is one page
|
||||
@@ -54,7 +54,7 @@ init$2:
|
||||
ld de,0 ; src adr is 0
|
||||
call ?move ; do it
|
||||
pop bc ; restore bank id's
|
||||
djnz init$2 ; loop till done
|
||||
djnz init$1 ; loop till done
|
||||
|
||||
endif
|
||||
|
||||
@@ -62,6 +62,35 @@ init$2:
|
||||
ld hl,signon$msg ; signon message
|
||||
call ?pmsg ; print it
|
||||
|
||||
if banked
|
||||
|
||||
; Confirm that HBIOS is configured with enough RAM banks
|
||||
; to accommodate banked version of CP/M 3. We use 2
|
||||
; additional banks which live below the user bank. So we
|
||||
; check that the these don't overlap with the RomWBW HBIOS
|
||||
; bank.
|
||||
|
||||
ld bc,0F8F2h ; HBIOS GET BNKINFO
|
||||
call 0FFF0h ; D: BIOS Bank, E: User Bank
|
||||
ld a,d
|
||||
ld (@hbbio),a
|
||||
ld a,e
|
||||
ld (@hbusr),a
|
||||
|
||||
sub 3 ; 2 extra banks (+1 for compare)
|
||||
cp d ; lowest cpm bank - hbios bank
|
||||
jr nc,init$2 ; continue if space available
|
||||
|
||||
ld hl,noram$msg ; signon message
|
||||
call ?pmsg ; print it
|
||||
|
||||
ld b,0F0h ; HBIOS system reset
|
||||
ld c,1h ; reset type warm (back to loader)
|
||||
call 0FFFFh ; do it
|
||||
|
||||
endif
|
||||
|
||||
init$2:
|
||||
; Check for HBIOS/CBIOS mismatch
|
||||
ld b,0F1h ; hbios version
|
||||
rst 08 ; do it, de=maj/min/up/pat
|
||||
@@ -731,6 +760,10 @@ clrflg db 0 ; RAM disk cleared flag
|
||||
clr$msg db 'RAM Disk Initialized',13,10,13,10,0
|
||||
vermis$msg db 7,'*** WARNING: HBIOS/CBIOS Version Mismatch ***',13,10,13,10,0
|
||||
|
||||
if banked
|
||||
noram$msg db 7,'*** ERROR: Insufficient RAM for banked CP/M 3 ***',13,10,13,10,0
|
||||
endif
|
||||
|
||||
if zpm
|
||||
|
||||
signon$msg db 13,10,'ZPM3'
|
||||
|
||||
@@ -22,4 +22,5 @@ pushd Prop && call Clean & popd
|
||||
pushd RomDsk && call Clean & popd
|
||||
pushd Doc && call Clean & popd
|
||||
pushd ZRC && call Clean & popd
|
||||
pushd Z1RCC && call Clean & popd
|
||||
pushd ZZRCC && call Clean & popd
|
||||
|
||||
@@ -201,6 +201,7 @@ below, **carefully** pick the appropriate ROM image for your hardware.
|
||||
| [Nhyodyne Z80 MBC]^1^ | MBC | MBC_std.rom | 38400 |
|
||||
| [Rhyophyre Z180 SBC]^1^ | - | RPH_std.rom | 38400 |
|
||||
| [Z80 ZRC CPU Module]^7^ | RCBus | RCZ80_zrc.rom | 115200 |
|
||||
| [Z180 Z1RCC CPU Module]^7^ | RCBus | RCZ180_z1rcc.rom | 115200 |
|
||||
| [Z280 ZZRCC CPU Module]^7^ | RCBus | RCZ280_zzrc.rom | 115200 |
|
||||
| [Z280 ZZ80MB SBC]^7^ | RCBus | RCZ280_zz80mb.rom | 115200 |
|
||||
| [Z80-Retro SBC]^8^ | - | Z80RETRO_std.rom | 38400 |
|
||||
@@ -595,6 +596,14 @@ technique is useful when:
|
||||
The RAM disk and ROM disk drives will be available even if you have
|
||||
no physical disk devices attached to your system.
|
||||
|
||||
Booting an operating system from ROM is not intended as a way to use
|
||||
your operating system on a long-term basis. The ROM disk has only
|
||||
a small subset of the operating system files. Additionally, you
|
||||
cannot easily customize your ROM disk because you cannot write to it.
|
||||
For any significant use of an operating system, you should boot directly
|
||||
to the disk/slice that contains the complete operating system. This
|
||||
is described in the next section.
|
||||
|
||||
## Starting Operating Systems from Disk
|
||||
|
||||
In order to make use of the more sophisticated operating systems
|
||||
@@ -618,7 +627,7 @@ has been assigned to the disk and slice you selected to boot.
|
||||
|
||||
If you receive the error message "Disk not bootable!", you have
|
||||
either failed to properly initialize the disk and slice requested
|
||||
or you have selected the wrong disk/slice.
|
||||
or you have selected an invalid/unavailable disk/slice.
|
||||
|
||||
The following example shows a disk boot into the first slice of disk
|
||||
unit 4 which happens to be the CP/M 2.2 operating system on this disk.
|
||||
@@ -696,6 +705,26 @@ have specified. It does not know what operating system is at that
|
||||
location. The layout of operating systems on disk media is described in
|
||||
the Using Disks section of this document.
|
||||
|
||||
### Auto-Submit Batch Files
|
||||
|
||||
All of the operating systems supplied with RomWBW have the ability to
|
||||
execute a "batch" of commands by creating a batch submission file
|
||||
containing the commands to be executed. The specifics of using
|
||||
batch files in a specific operating system is covered in its specific
|
||||
documentation.
|
||||
|
||||
At boot, the operating system will look for a specific batch file
|
||||
(`PROFILE.SUB` for CP/M 2.2 and 3) on the boot drive and execute that
|
||||
batch file automatically. This allows you to automatically customize
|
||||
your operating system with any commands desired at boot. CP/M 2.2 did
|
||||
not originally have the ability to automatically excute a batch file at
|
||||
boot, but the CBIOS in RomWBW has added this capability.
|
||||
|
||||
Since RomWBW can utilize many disk slices, it is very easy to create
|
||||
slices for specific workflows (editing, software development, games,
|
||||
etc.). You can then just boot to the slice that is optimized for the
|
||||
task you want to perform.
|
||||
|
||||
## System Management
|
||||
|
||||
### Listing Disk Device Inventory
|
||||
@@ -901,7 +930,7 @@ Configuring Drives...
|
||||
```
|
||||
|
||||
You will probably see more drive letters than this. The drive letter
|
||||
assignment process is described below in the Drive Letter Assignment
|
||||
assignment process is described below in the [Drive Letter Assignment]
|
||||
section. Be aware that RomWBW will only assign drive letters to disk
|
||||
interfaces that actually have media in them. If you do not see drive
|
||||
letters assigned as expected, refer to the prior system boot messages
|
||||
@@ -992,6 +1021,69 @@ rest of the drive letters will be offset to accommodate this. This is
|
||||
done because most legacy operating systems expect that A: will be the
|
||||
boot drive.
|
||||
|
||||
### Default Drive Letter Assignment
|
||||
|
||||
As shown above, when an operating system is booted, RomWBW will
|
||||
automatically assign drive letters to physical disk devices. The
|
||||
assignment process varies depending on: 1) the drive/slice you choose to
|
||||
boot from, and 2) the number and type of physical drives in your
|
||||
system.
|
||||
|
||||
If you boot an operating system from ROM, then the first two drive
|
||||
letters will be assigned to your RAM disk (A:) and your ROM disk (B:).
|
||||
It may seem odd that the RAM disk is assigned to A: in this case. The
|
||||
reason for this is to accommodate certain functions that require that A:
|
||||
be a writable disk drive. For example, A: **must** be writable in order
|
||||
to submit batch files.
|
||||
|
||||
If you boot to a physical disk device, then the first drive letter (A:)
|
||||
will be assigned to the disk/slice that you chose to boot from. The A:
|
||||
drive letter is considered special by most operating systems and is
|
||||
automatically used in some cases. By making the selected disk/slice the
|
||||
A: drive, you can setup different disks/slices for specific uses and
|
||||
just boot to it.
|
||||
|
||||
After the first drive letter is assigned (as well as the second drive
|
||||
letter in the case of a ROM boot), RomWBW will assign additional drive
|
||||
letters based on the disk drives in the system. Additional drive
|
||||
letters will be assigned in the following order:
|
||||
|
||||
- RAM Disk
|
||||
- ROM Disk
|
||||
- Floppy Disk(s)
|
||||
- Hard Disk(s)
|
||||
|
||||
If a disk/slice was already assigned as the A: (or B:) drive letter,
|
||||
then it will not be assigned again.
|
||||
|
||||
In the case of floppy, RAM, and ROM disks, a single drive letter will be
|
||||
assigned to each physical disk (even if there is no disk media in the
|
||||
drive).
|
||||
|
||||
In the case of hard disks, 1-8 drive letters will be assigned to the
|
||||
initial 1-8 slices of the disk drive. The number of drive letters
|
||||
assigned to each hard disk depends on the number of hard disks in the
|
||||
system:
|
||||
|
||||
- 1 Hard Disk: 8 drive letters (slices)
|
||||
- 2 Hard Disks: 4 drive letters (slices) per disk
|
||||
- 3+ Hard Disks: 2 drive letters (slices) per disk
|
||||
|
||||
This somewhat complicated algorithm is used to try and maximize the
|
||||
limited number of operating system drive letters available (16) to
|
||||
the available disk devices as evenly as possible.
|
||||
|
||||
Note that for hard disk devices, drive letters will only be assigned
|
||||
to disk devices that actually contain media. So, for example, if you
|
||||
have an SD Card slot in your system, but it has no SD Card inserted, then
|
||||
no drive letters will be assigned to it.
|
||||
|
||||
Since drive letter assignments are easily changed at any time using the
|
||||
`ASSIGN` command, you can customize your assignments as desired after
|
||||
starting the operating system. Even better, you can use an auto-submit
|
||||
batch file to customzie the assignments at startup without any user
|
||||
intervention.
|
||||
|
||||
## ROM & RAM Disks
|
||||
|
||||
A typical RomWBW system has 512KB of ROM and 512KB of RAM. Some
|
||||
@@ -1609,7 +1701,7 @@ filesystem partition and any CP/M filesystem slices that don't fit. You
|
||||
will get "no disk" errors if you attempt to access a slice past the
|
||||
end of the physical hard disk.
|
||||
|
||||
**WARNING**:Your hard disk may be too small to contain the full 64
|
||||
**WARNING**: Your hard disk may be too small to contain the full 64
|
||||
CP/M filesystem slices. The true number of CP/M filesystem slices that
|
||||
will fit on your specific physical hard disk can be calculated as
|
||||
described in [Hard Disk Capacity].
|
||||
@@ -1625,12 +1717,20 @@ them using `CLRDIR` first.
|
||||
|
||||
A great way to maintain your own data on a hard disk is to put this
|
||||
data in slices beyond the first 6. By doing so, you can always
|
||||
"reimage" your drive with the combo image without overlaying the data
|
||||
"re-image" your drive with the combo image without overlaying the data
|
||||
stored in the slices beyond the first 6. Just be very careful to use
|
||||
the same combo image layout (hd512 or hd1k) as you used originally.
|
||||
Also remember to calculate the maximum number of slices your hard disk
|
||||
will support and do not exceed this number.
|
||||
|
||||
**WARNING**: The combo disk image includes a partition table at the
|
||||
start of the image. If you re-image drive with the combo image, you
|
||||
will overwrite this partition table. This is fine as long as you don't
|
||||
make any changes to the partition table. If you manually customize the
|
||||
partition table (using `FDISK80` or other partition management
|
||||
software), those changes will be lost if you re-image your disk with a
|
||||
new combo disk image.
|
||||
|
||||
#### Custom Hard Disk Image
|
||||
|
||||
If you want to use specific slices in a specific order, you can easily
|
||||
@@ -1640,8 +1740,9 @@ For hard disks, each .img file represents a single slice (CP/M
|
||||
filesystem). Since a hard disk can contain many slices, you can just
|
||||
concatenate the slices (.img files) together to create your desired hard
|
||||
disk image. For example, if you want to create a hard disk image that
|
||||
has slices for CP/M 2.2, CP/M 3, and WordStar in the hd512 format, you would use
|
||||
the command line of your modern computer to create the final image:
|
||||
has slices for CP/M 2.2, CP/M 3, and WordStar in the hd512 format, you
|
||||
would use the command line of your modern computer to create the final
|
||||
image:
|
||||
|
||||
Windows:
|
||||
|
||||
@@ -2651,6 +2752,166 @@ SAMPLE2.TXT ==> 4:/SAMPLE2.TXT ... [OK]
|
||||
2 File(s) Copied
|
||||
```
|
||||
|
||||
# Real Time Clock
|
||||
|
||||
RomWBW supports a variety of real time clock hardware. If your
|
||||
system has this hardware, then it will be able to maintain the
|
||||
current date and time even while your system is turned off.
|
||||
Additionally, depending on the operating system being used, you may be
|
||||
able to utilize date/time stamping of files.
|
||||
|
||||
You can determine if your system has a real time clock present (and
|
||||
functioning) by looking at the boot messages. Here is an example of
|
||||
a boot message reflecting the detection of a valid real time clock
|
||||
module:
|
||||
|
||||
`DSRTC: MODE=STD IO=0x8A Thu 2023-10-19 14:07:11 CHARGE=ON`
|
||||
|
||||
This example is from a DSRTC clock module. You may have a different
|
||||
one, but it will always display the current date/time.
|
||||
|
||||
In some cases, your real time clock will support charging of the
|
||||
battery or super-capacitor while the system has power. The status of
|
||||
this charging is displayed.
|
||||
|
||||
If the date/time of your RTC needs to be updated, you will need to do
|
||||
this with one of the utilities described below. There is no ability to
|
||||
update the date/time of the RTC in the RomWBW Boot Loader or Monitor.
|
||||
|
||||
## Date/Time Utilities
|
||||
|
||||
RomwWBW includes two utilities for displaying or setting the date/time
|
||||
stored by the RTC. They are both a bit different and are briefly
|
||||
described below.
|
||||
|
||||
### WDATE Utility
|
||||
|
||||
The `WDATE` utility (contributed by Kevin Boone) is an application
|
||||
that will display and/or update the current date/time. Its operation is
|
||||
described in $doc_apps$. This utility works with any of the supported
|
||||
RomWBW RTC hardware. Here is an example of displaying and updating the
|
||||
date/time with this utility:
|
||||
|
||||
```
|
||||
A>wdate
|
||||
Thursday 19 October 14:14:43 2023
|
||||
|
||||
A>wdate 23 10 19 14 24 30
|
||||
|
||||
A>wdate
|
||||
Thursday 19 October 14:24:34 2023
|
||||
|
||||
```
|
||||
|
||||
Note that `WDATE` does not have anything to do with date/time stamping
|
||||
of files. It merely displays and sets the real time clock value.
|
||||
|
||||
### RTC Utility
|
||||
|
||||
Like `WDATE`, the `RTC` utility (contributed by Andrew Lynch) will let
|
||||
you display and set the current date/time. However, this utility only
|
||||
works with the DSRTC hardware (DS1302 chip). It is a "direct to
|
||||
hardware application". Its operation is described in $doc_apps$. Here
|
||||
is an example of displaying and updatting the date/time with this
|
||||
utility:
|
||||
|
||||
```
|
||||
A>rtc
|
||||
Start RTC Program
|
||||
RomWBW HBIOS, Mark 4 RTC Latch Port 0x8A
|
||||
|
||||
RTC: Version 1.9
|
||||
Commands: E)xit T)ime st(A)rt S)et R)aw L)oop C)harge N)ocharge D)elay I)nit G)et P)ut B)oot W)arm-start H)elp
|
||||
|
||||
RTC>t
|
||||
Current time: 23-10-19 14:30:25-05
|
||||
|
||||
RTC>i
|
||||
Init date/time.
|
||||
|
||||
YEAR:23
|
||||
MONTH:10
|
||||
DATE:19
|
||||
HOURS:14
|
||||
MINUTES:31
|
||||
SECONDS:00
|
||||
DAY:05
|
||||
```
|
||||
|
||||
The `RTC` utility is also capable of turning the charging feature of
|
||||
the DS1320 chip on or off. Here is an example of turning if off and
|
||||
back on:
|
||||
|
||||
```
|
||||
|
||||
A>rtc
|
||||
Start RTC Program
|
||||
RomWBW HBIOS, Mark 4 RTC Latch Port 0x8A
|
||||
|
||||
|
||||
RTC: Version 1.9
|
||||
Commands: E)xit T)ime st(A)rt S)et R)aw L)oop C)harge N)ocharge D)elay I)nit G)et P)ut B)oot W)arm-start H)elp
|
||||
|
||||
RTC>n
|
||||
Trickle charger disabled.
|
||||
|
||||
RTC>c
|
||||
Trickle charger enabled.
|
||||
```
|
||||
|
||||
Do **not** enable charging unless you are sure that your system
|
||||
supports this. If your RTC is being powered by a normal battery, it
|
||||
would be dangerous to enable charging.
|
||||
|
||||
## Date/Time File Stamping
|
||||
|
||||
If an RTC is available in your system, then most operating systems
|
||||
can use it to date/time stamp files. This just means recording the
|
||||
date/time of file creation, update, and or access in the directory.
|
||||
This capability is available in all of the RomWBW operating system
|
||||
except the original DRI CP/M 2.2.
|
||||
|
||||
In some cases (such as ZSDOS), you must load an RSX (memory resident
|
||||
utility) to enable date/time stamping of files. Additionally, you
|
||||
will need to initialize the directory. The procedure varies in each
|
||||
operation system, so you must review the associated documentation.
|
||||
|
||||
The date/time stamping mechanisms for each operating system are
|
||||
generally not compatible. If you initialize a directory for a type
|
||||
of stamping, you should be careful not to manipulate that directory
|
||||
with a different operating system with a different date/time stamping
|
||||
mechanism. Doing so may corrupt the directory.
|
||||
|
||||
The RomWBW disk images do not have date/time stamping initialized. This
|
||||
is to avoid any chance of directory corruption.
|
||||
|
||||
## Timezone
|
||||
|
||||
None of the operating systems distributed with RomWBW have any concept
|
||||
of timezone. When files are date/time stamped, the date/time will
|
||||
simply be whatever date/time the RTC currently has.
|
||||
|
||||
The normal practice is to set the RTC to your local time. This implies
|
||||
that you would need to manually adjust the RTC for daylight savings time
|
||||
and/or when you travel to a different time zone.
|
||||
|
||||
The date/time stamps of files in directories will also be stored in
|
||||
local time. This includes files stored in a FAT filesystem. If you
|
||||
subsequently view the directory from modern machines (Windows, Linux,
|
||||
etc.), the date/time displayed will depend on the behavior of the
|
||||
modern system.
|
||||
|
||||
For example, Linux assumes that the date/time of files
|
||||
is UTC. So, if you create a file on a FAT filesystem with your RomWBW
|
||||
computer and then use Linux to view the directory, the date/time stamps
|
||||
will seem "off" by a few hours.
|
||||
|
||||
The only alternative you may consider is setting the date/time of your
|
||||
RTC to UTC. Since UTC is consistent across all timezones and daylight
|
||||
savings time, your file date/time stamps will also be consistent. Of
|
||||
course, this will mean that your RomWBW computer will display a
|
||||
date/time that seems wrong because it is not local time.
|
||||
|
||||
# CP/NET Networking
|
||||
|
||||
Digital Research created a simple network file sharing system called
|
||||
@@ -3348,8 +3609,10 @@ directed to complete a partial flash using the /P command line switch.
|
||||
# Related Projects
|
||||
|
||||
Outside of the hardware platforms adapted to RomWBW, there are a variety
|
||||
of software projects that either target RomWBW specifically or provide
|
||||
a RomWBW-specific variation.
|
||||
of projects that either target RomWBW specifically or provide
|
||||
a RomWBW-specific variation. These efforts are greatly appreciated
|
||||
and are listed below. Please contact the author if there are any other
|
||||
such projects that are not listed.
|
||||
|
||||
## Z88DK
|
||||
|
||||
@@ -3385,6 +3648,16 @@ the CP/M OS variants. This tool (`WDATE`) is included on the RomWBW
|
||||
OS disk images. The project is hosted at
|
||||
<https://github.com/kevinboone/wdate-cpm>.
|
||||
|
||||
## Assembly Language Programming for the RC2014 Zed
|
||||
|
||||
Bruce Hall has written a very nice document that describes how to
|
||||
develop assembly language applications on RomWBW. It begins with the
|
||||
setup and configuration of a new RC2014 Zed system running RomWBW.
|
||||
It describes not only generic CP/M application development, but also
|
||||
RomWBW HBIOS programming and bare metal programming. The latest copy
|
||||
of this document is hosted at
|
||||
[http://w8bh.net/Assembly for RC2014Z.pdf](http://w8bh.net/Assembly%20for%20RC2014Z.pdf).
|
||||
|
||||
# Acknowledgments
|
||||
|
||||
I want to acknowledge that a great deal of the code and inspiration
|
||||
@@ -4074,7 +4347,29 @@ the RomWBW HBIOS configuration.
|
||||
- VGARC Video & Keyboard Module
|
||||
- Serial baud rate is usually determined by hardware for ACIA and
|
||||
SIO interfaces
|
||||
|
||||
### Z180 Z1RCC CPU Module
|
||||
|
||||
| | |
|
||||
|-------------------|--------------------|
|
||||
| ROM Image Files | RCZ180_z1rcc.rom |
|
||||
| Console Baud Rate | 115200 |
|
||||
| Interrupts | Mode 2 |
|
||||
|
||||
- CPU speed is detected at startup if DS1302 RTC is active
|
||||
- Otherwise 18.432 MHz assumed
|
||||
- System timer is generated by Z180 CPU
|
||||
- Hardware auto-detected:
|
||||
- DS1302 RTC
|
||||
- Z180 ASCI Serial Ports
|
||||
- SIO Serial Interface Module
|
||||
- EP Dual UART Serial Interface Module
|
||||
- WDC Floppy Disk Controller w/ 3.5" HD Drives
|
||||
- IDE Hard Disk Interface Module
|
||||
- PPIDE Hard Disk Interface Module
|
||||
- Use of Interrupt Mode 2 requires proper IEI/IEO configuration
|
||||
for all peripherals generating interrupts
|
||||
|
||||
`\clearpage`{=latex}
|
||||
|
||||
### Z280 ZZRCC CPU Module
|
||||
|
||||
@@ -216,6 +216,7 @@ call Build RCZ80 zrc || exit /b
|
||||
call Build RCZ80 zrc_ram || exit /b
|
||||
call Build RCZ180 ext || exit /b
|
||||
call Build RCZ180 nat || exit /b
|
||||
call Build RCZ180 z1rcc || exit /b
|
||||
call Build RCZ280 ext || exit /b
|
||||
call Build RCZ280 nat || exit /b
|
||||
call Build RCZ280 zz80mb || exit /b
|
||||
|
||||
@@ -15,6 +15,7 @@ if [ "${ROM_PLATFORM}" == "dist" ] ; then
|
||||
ROM_PLATFORM="N8"; ROM_CONFIG="std"; bash Build.sh
|
||||
ROM_PLATFORM="RCZ180"; ROM_CONFIG="ext"; bash Build.sh
|
||||
ROM_PLATFORM="RCZ180"; ROM_CONFIG="nat"; bash Build.sh
|
||||
ROM_PLATFORM="RCZ180"; ROM_CONFIG="z1rcc"; bash Build.sh
|
||||
ROM_PLATFORM="RCZ280"; ROM_CONFIG="ext"; bash Build.sh
|
||||
ROM_PLATFORM="RCZ280"; ROM_CONFIG="nat"; bash Build.sh
|
||||
ROM_PLATFORM="RCZ280"; ROM_CONFIG="zz80mb"; bash Build.sh
|
||||
|
||||
76
Source/HBIOS/Config/RCZ180_z1rcc.asm
Normal file
76
Source/HBIOS/Config/RCZ180_z1rcc.asm
Normal file
@@ -0,0 +1,76 @@
|
||||
;
|
||||
;==================================================================================================
|
||||
; RCBUS Z180 Z1RCC CONFIGURATION (ROMLESS)
|
||||
;==================================================================================================
|
||||
;
|
||||
; THE COMPLETE SET OF DEFAULT CONFIGURATION SETTINGS FOR THIS PLATFORM ARE FOUND IN THE
|
||||
; CFG_<PLT>.ASM INCLUDED FILE WHICH IS FOUND IN THE PARENT DIRECTORY. THIS FILE CONTAINS
|
||||
; COMMON CONFIGURATION SETTINGS THAT OVERRIDE THE DEFAULTS. IT IS INTENDED THAT YOU MAKE
|
||||
; YOUR CUSTOMIZATIONS IN THIS FILE AND JUST INHERIT ALL OTHER SETTINGS FROM THE DEFAULTS.
|
||||
; EVEN BETTER, YOU CAN MAKE A COPY OF THIS FILE WITH A NAME LIKE <PLT>_XXX.ASM AND SPECIFY
|
||||
; YOUR FILE IN THE BUILD PROCESS.
|
||||
;
|
||||
; THE SETTINGS BELOW ARE THE SETTINGS THAT ARE MOST COMMONLY MODIFIED FOR THIS PLATFORM.
|
||||
; MANY OF THEM ARE EQUAL TO THE SETTINGS IN THE INCLUDED FILE, SO THEY DON'T REALLY DO
|
||||
; ANYTHING AS IS. THEY ARE LISTED HERE TO MAKE IT EASY FOR YOU TO ADJUST THE MOST COMMON
|
||||
; SETTINGS.
|
||||
;
|
||||
; N.B., SINCE THE SETTINGS BELOW ARE REDEFINING VALUES ALREADY SET IN THE INCLUDED FILE,
|
||||
; TASM INSISTS THAT YOU USE THE .SET OPERATOR AND NOT THE .EQU OPERATOR BELOW. ATTEMPTING
|
||||
; TO REDEFINE A VALUE WITH .EQU BELOW WILL CAUSE TASM ERRORS!
|
||||
;
|
||||
; PLEASE REFER TO THE CUSTOM BUILD INSTRUCTIONS (README.TXT) IN THE SOURCE DIRECTORY (TWO
|
||||
; DIRECTORIES ABOVE THIS ONE).
|
||||
;
|
||||
#DEFINE PLATFORM_NAME "Z1RCC", " [", CONFIG, "]"
|
||||
;
|
||||
#DEFINE BOOT_DEFAULT "H" ; DEFAULT BOOT LOADER CMD ON <CR> OR AUTO BOOT
|
||||
;
|
||||
#include "cfg_rcz180.asm"
|
||||
;
|
||||
CPUOSC .SET 18432000 ; CPU OSC FREQ IN MHZ
|
||||
CRTACT .SET FALSE ; ACTIVATE CRT (VDU,CVDU,PROPIO,ETC) AT STARTUP
|
||||
;
|
||||
FPLED_ENABLE .SET TRUE ; FP: ENABLES FRONT PANEL LEDS
|
||||
FPSW_ENABLE .SET TRUE ; FP: ENABLES FRONT PANEL SWITCHES
|
||||
;
|
||||
MEMMGR .SET MM_Z180 ; MEMORY MANAGER: MM_[SBC|Z2|N8|Z180]
|
||||
;
|
||||
RAMSIZE .SET 512 ; SIZE OF RAM IN KB (MUST MATCH YOUR HARDWARE!!!)
|
||||
ROMSIZE .SET 0 ; SIZE OF ROM IN KB (MUST MATCH YOUR HARDWARE!!!)
|
||||
;
|
||||
Z180_CLKDIV .SET 1 ; Z180: CHK DIV: 0=OSC/2, 1=OSC, 2=OSC*2
|
||||
Z180_MEMWAIT .SET 0 ; Z180: MEMORY WAIT STATES (0-3)
|
||||
Z180_IOWAIT .SET 1 ; Z180: I/O WAIT STATES TO ADD ABOVE 1 W/S BUILT-IN (0-3)
|
||||
;
|
||||
MDROM .SET FALSE ; MD: ENABLE ROM DISK
|
||||
MDRAM .SET TRUE ; MD: ENABLE RAM DISK
|
||||
;
|
||||
DSRTCENABLE .SET TRUE ; DSRTC: ENABLE DS-1302 CLOCK DRIVER (DSRTC.ASM)
|
||||
INTRTCENABLE .SET TRUE ; ENABLE PERIODIC INTERRUPT CLOCK DRIVER (INTRTC.ASM)
|
||||
;
|
||||
UARTENABLE .SET TRUE ; UART: ENABLE 8250/16550-LIKE SERIAL DRIVER (UART.ASM)
|
||||
ASCIENABLE .SET TRUE ; ASCI: ENABLE Z180 ASCI SERIAL DRIVER (ASCI.ASM)
|
||||
ACIAENABLE .SET FALSE ; ACIA: ENABLE MOTOROLA 6850 ACIA DRIVER (ACIA.ASM)
|
||||
SIOENABLE .SET TRUE ; SIO: ENABLE ZILOG SIO SERIAL DRIVER (SIO.ASM)
|
||||
;
|
||||
TMSENABLE .SET FALSE ; TMS: ENABLE TMS9918 VIDEO/KBD DRIVER (TMS.ASM)
|
||||
TMSMODE .SET TMSMODE_MSX ; TMS: DRIVER MODE: TMSMODE_[SCG|N8|MBC|MSX|MSX9958|MSXKBD|COLECO]
|
||||
MKYENABLE .SET FALSE ; MSX 5255 PPI KEYBOARD COMPATIBLE DRIVER (REQUIRES TMS VDA DRIVER)
|
||||
VRCENABLE .SET FALSE ; VRC: ENABLE VGARC VIDEO/KBD DRIVER (VRC.ASM)
|
||||
VDAEMU_SERKBD .SET 0 ; VDA EMULATION: SERIAL KBD UNIT #, OR $FF FOR HW KBD
|
||||
;
|
||||
;
|
||||
AY38910ENABLE .SET FALSE ; AY: AY-3-8910 / YM2149 SOUND DRIVER
|
||||
AYMODE .SET AYMODE_RCZ180 ; AY: DRIVER MODE: AYMODE_[SCG|N8|RCZ80|RCZ180|MSX|LINC]
|
||||
SN76489ENABLE .SET FALSE ; SN: ENABLE SN76489 SOUND DRIVER
|
||||
;
|
||||
FDENABLE .SET TRUE ; FD: ENABLE FLOPPY DISK DRIVER (FD.ASM)
|
||||
FDMODE .SET FDMODE_RCWDC ; FD: DRIVER MODE: FDMODE_[DIO|ZETA|ZETA2|DIDE|N8|DIO3|RCSMC|RCWDC|DYNO|EPFDC]
|
||||
;
|
||||
IDEENABLE .SET TRUE ; IDE: ENABLE IDE DISK DRIVER (IDE.ASM)
|
||||
PPIDEENABLE .SET TRUE ; PPIDE: ENABLE PARALLEL PORT IDE DISK DRIVER (PPIDE.ASM)
|
||||
SDENABLE .SET FALSE ; SD: ENABLE SD CARD DISK DRIVER (SD.ASM)
|
||||
SDCNT .SET 1 ; SD: NUMBER OF SD CARD DEVICES (1-2), FOR DSD/SC/MT SC ONLY
|
||||
;
|
||||
PRPENABLE .SET FALSE ; PRP: ENABLE ECB PROPELLER IO BOARD DRIVER (PRP.ASM)
|
||||
@@ -178,10 +178,26 @@ ACIA1_INT:
|
||||
;
|
||||
ACIA_INTRCV:
|
||||
; CHECK TO SEE IF SOMETHING IS ACTUALLY THERE
|
||||
CALL DELAY
|
||||
LD C,(IY+3) ; CMD/STAT PORT TO C
|
||||
IN A,(C) ; GET STATUS
|
||||
RRA ; READY BIT TO CF
|
||||
RET NC ; NOTHING AVAILABLE ON CURRENT CHANNEL
|
||||
LD B,A
|
||||
AND $01 ; ISOLATE READY BIT
|
||||
JR NZ,ACIA_INTRCV1
|
||||
;
|
||||
#IF FALSE
|
||||
CALL PC_LT
|
||||
LD A,B
|
||||
CALL PRTHEXBYTE
|
||||
INC C
|
||||
IN A,(C)
|
||||
CALL PRTHEXBYTE
|
||||
CALL PC_GT
|
||||
OR $FF
|
||||
#ENDIF
|
||||
;
|
||||
RET
|
||||
|
||||
;
|
||||
ACIA_INTRCV1:
|
||||
; RECEIVE CHARACTER INTO BUFFER
|
||||
|
||||
@@ -46,15 +46,15 @@ RTCIO .EQU $94 ; RTC LATCH REGISTER ADR
|
||||
KIOENABLE .EQU FALSE ; ENABLE ZILOG KIO SUPPORT
|
||||
KIOBASE .EQU $80 ; KIO BASE I/O ADDRESS
|
||||
;
|
||||
CTCENABLE .EQU FALSE ; ENABLE ZILOG CTC SUPPORT
|
||||
CTCENABLE .EQU TRUE ; ENABLE ZILOG CTC SUPPORT
|
||||
CTCDEBUG .EQU FALSE ; ENABLE CTC DRIVER DEBUG OUTPUT
|
||||
CTCBASE .EQU $B0 ; CTC BASE I/O ADDRESS
|
||||
CTCBASE .EQU $60 ; CTC BASE I/O ADDRESS
|
||||
CTCTIMER .EQU TRUE ; ENABLE CTC PERIODIC TIMER
|
||||
CTCMODE .EQU CTCMODE_CTR ; CTC MODE: CTCMODE_[NONE|CTR|TIM16|TIM256]
|
||||
CTCPRE .EQU 256 ; PRESCALE CONSTANT (1-256)
|
||||
CTCPRECH .EQU 2 ; PRESCALE CHANNEL (0-3)
|
||||
CTCTIMCH .EQU 3 ; TIMER CHANNEL (0-3)
|
||||
CTCOSC .EQU (4915200/8) ; CTC CLOCK FREQUENCY
|
||||
CTCOSC .EQU (7372800/8) ; CTC CLOCK FREQUENCY
|
||||
;
|
||||
PCFENABLE .EQU FALSE ; ENABLE PCF8584 I2C CONTROLLER
|
||||
PCFBASE .EQU $56 ; PCF8584 BASE I/O ADDRESS
|
||||
@@ -88,6 +88,7 @@ PKDOSC .EQU 3000000 ; OSCILLATOR FREQ FOR PKD (IN HZ)
|
||||
H8PENABLE .EQU FALSE ; ENABLES HEATH H8 FRONT PANEL
|
||||
;
|
||||
BOOTCON .EQU 0 ; BOOT CONSOLE DEVICE
|
||||
SECCON .EQU $FF ; SECONDARY CONSOLE DEVICE
|
||||
CRTACT .EQU FALSE ; ACTIVATE CRT (VDU,CVDU,PROPIO,ETC) AT STARTUP
|
||||
VDAEMU .EQU EMUTYP_ANSI ; VDA EMULATION: EMUTYP_[TTY|ANSI]
|
||||
VDAEMU_SERKBD .EQU $FF ; VDA EMULATION: SERIAL KBD UNIT #, OR $FF FOR HW KBD
|
||||
@@ -122,17 +123,18 @@ DS7RTCMODE .EQU DS7RTCMODE_PCF ; DS7RTC: OPERATING MODE: DS7RTC_[PCF]
|
||||
DUARTENABLE .EQU FALSE ; DUART: ENABLE 2681/2692 SERIAL DRIVER (DUART.ASM)
|
||||
;
|
||||
UARTENABLE .EQU TRUE ; UART: ENABLE 8250/16550-LIKE SERIAL DRIVER (UART.ASM)
|
||||
UARTOSC .EQU 1843200 ; UART: OSC FREQUENCY IN MHZ
|
||||
UARTOSC .EQU 7372800 ; UART: OSC FREQUENCY IN MHZ
|
||||
UARTINTS .EQU FALSE ; UART: INCLUDE INTERRUPT SUPPORT UNDER IM1/2/3
|
||||
UARTCFG .EQU DEFSERCFG ; UART: LINE CONFIG FOR UART PORTS
|
||||
UARTCASSPD .EQU SER_300_8N1 ; UART: ECB CASSETTE UART DEFAULT SPEED
|
||||
UARTSBC .EQU TRUE ; UART: AUTO-DETECT SBC/ZETA/DUO ONBOARD UART
|
||||
UARTSBCFORCE .EQU FALSE ; UART: FORCE DETECTION OF SBC UART (FOR SIMH)
|
||||
UARTAUX .EQU TRUE ; UART: AUTO-DETECT AUX UART
|
||||
UARTCAS .EQU FALSE ; UART: AUTO-DETECT ECB CASSETTE UART
|
||||
UARTMFP .EQU FALSE ; UART: AUTO-DETECT MF/PIC UART
|
||||
UART4 .EQU FALSE ; UART: AUTO-DETECT 4UART UART
|
||||
UARTRC .EQU FALSE ; UART: AUTO-DETECT RC UART
|
||||
UARTDUAL .EQU FALSE ; UART: AUTO-DETECT DUAL UART
|
||||
UARTDUAL .EQU TRUE ; UART: AUTO-DETECT DUAL UART
|
||||
;
|
||||
ASCIENABLE .EQU FALSE ; ASCI: ENABLE Z180 ASCI SERIAL DRIVER (ASCI.ASM)
|
||||
;
|
||||
@@ -140,18 +142,18 @@ Z2UENABLE .EQU FALSE ; Z2U: ENABLE Z280 UART SERIAL DRIVER (Z2U.ASM)
|
||||
;
|
||||
ACIAENABLE .EQU FALSE ; ACIA: ENABLE MOTOROLA 6850 ACIA DRIVER (ACIA.ASM)
|
||||
;
|
||||
SIOENABLE .EQU FALSE ; SIO: ENABLE ZILOG SIO SERIAL DRIVER (SIO.ASM)
|
||||
SIOENABLE .EQU TRUE ; SIO: ENABLE ZILOG SIO SERIAL DRIVER (SIO.ASM)
|
||||
SIODEBUG .EQU FALSE ; SIO: ENABLE DEBUG OUTPUT
|
||||
SIOBOOT .EQU 0 ; SIO: REBOOT ON RCV CHAR (0=DISABLED)
|
||||
SIOCNT .EQU 1 ; SIO: NUMBER OF CHIPS TO DETECT (1-2), 2 CHANNELS PER CHIP
|
||||
SIO0MODE .EQU SIOMODE_ZP ; SIO 0: CHIP TYPE: SIOMODE_[STD|RC|SMB|ZP|Z80R]
|
||||
SIO0BASE .EQU $B0 ; SIO 0: REGISTERS BASE ADR
|
||||
SIO0ACLK .EQU (4915200/8) ; SIO 0A: OSC FREQ IN HZ, ZP=2457600/4915200, RC/SMB=7372800
|
||||
SIO0BASE .EQU $60 ; SIO 0: REGISTERS BASE ADR
|
||||
SIO0ACLK .EQU (7372800/4) ; SIO 0A: OSC FREQ IN HZ, ZP=2457600/4915200, RC/SMB=7372800
|
||||
SIO0ACFG .EQU DEFSERCFG ; SIO 0A: SERIAL LINE CONFIG
|
||||
SIO0ACTCC .EQU -1 ; SIO 0A: CTC CHANNEL 0=A, 1=B, 2=C, 3=D, -1 FOR NONE
|
||||
SIO0BCLK .EQU (4915200/8) ; SIO 0B: OSC FREQ IN HZ, ZP=2457600/4915200, RC/SMB=7372800
|
||||
SIO0ACTCC .EQU 0 ; SIO 0A: CTC CHANNEL 0=A, 1=B, 2=C, 3=D, -1 FOR NONE
|
||||
SIO0BCLK .EQU (7372800/4) ; SIO 0B: OSC FREQ IN HZ, ZP=2457600/4915200, RC/SMB=7372800
|
||||
SIO0BCFG .EQU DEFSERCFG ; SIO 0B: SERIAL LINE CONFIG
|
||||
SIO0BCTCC .EQU -1 ; SIO 0B: CTC CHANNEL 0=A, 1=B, 2=C, 3=D, -1 FOR NONE
|
||||
SIO0BCTCC .EQU 1 ; SIO 0B: CTC CHANNEL 0=A, 1=B, 2=C, 3=D, -1 FOR NONE
|
||||
;
|
||||
XIOCFG .EQU DEFSERCFG ; XIO: SERIAL LINE CONFIG
|
||||
;
|
||||
@@ -229,14 +231,14 @@ SDCNT .EQU 1 ; SD: NUMBER OF SD CARD DEVICES (1-2), FOR DSD/SC/MT ONLY
|
||||
SDTRACE .EQU 1 ; SD: TRACE LEVEL (0=NO,1=ERRORS,2=ALL)
|
||||
SDCSIOFAST .EQU FALSE ; SD: ENABLE TABLE-DRIVEN BIT INVERTER IN CSIO MODE
|
||||
;
|
||||
CHENABLE .EQU FALSE ; CH: ENABLE CH375/376 USB SUPPORT
|
||||
CHENABLE .EQU TRUE ; CH: ENABLE CH375/376 USB SUPPORT
|
||||
CHTRACE .EQU 1 ; CH: TRACE LEVEL (0=NO,1=ERRORS,2=ALL)
|
||||
CHUSBTRACE .EQU 1 ; CHUSB: TRACE LEVEL (0=NO,1=ERRORS,2=ALL)
|
||||
CHSDTRACE .EQU 1 ; CHSD: TRACE LEVEL (0=NO,1=ERRORS,2=ALL)
|
||||
CHCNT .EQU 1 ; CH: NUMBER OF BOARDS TO DETECT (1-2)
|
||||
CH0BASE .EQU $BE ; CH 0: BASE I/O ADDRESS
|
||||
CH0BASE .EQU $4E ; CH 0: BASE I/O ADDRESS
|
||||
CH0USBENABLE .EQU TRUE ; CH 0: ENABLE USB DISK
|
||||
CH0SDENABLE .EQU FALSE ; CH 0: ENABLE SD DISK
|
||||
CH0SDENABLE .EQU TRUE ; CH 0: ENABLE SD DISK
|
||||
CH1BASE .EQU $FF ; CH 1: BASE I/O ADDRESS
|
||||
CH1USBENABLE .EQU FALSE ; CH 1: ENABLE USB DISK
|
||||
CH1SDENABLE .EQU FALSE ; CH 1: ENABLE SD DISK
|
||||
@@ -254,16 +256,16 @@ ESPCONENABLE .EQU TRUE ; ESP: ENABLE ESP32 CONSOLE IO DRIVER VIDEO/KBD SUPPORT
|
||||
HDSKENABLE .EQU FALSE ; HDSK: ENABLE SIMH HDSK DISK DRIVER (HDSK.ASM)
|
||||
HDSKTRACE .EQU 1 ; HDSK: TRACE LEVEL (0=NO,1=ERRORS,2=ALL)
|
||||
;
|
||||
PIOENABLE .EQU FALSE ; PIO: ENABLE ZILOG PIO DRIVER (PIO.ASM)
|
||||
PIOENABLE .EQU TRUE ; PIO: ENABLE ZILOG PIO DRIVER (PIO.ASM)
|
||||
PIOCNT .EQU 2 ; PIO: NUMBER OF CHIPS TO DETECT (1-2), 2 CHANNELS PER CHIP
|
||||
PIO0BASE .EQU $B8 ; PIO 0: REGISTERS BASE ADR
|
||||
PIO1BASE .EQU $BC ; PIO 1: REGISTERS BASE ADR
|
||||
PIO0BASE .EQU $68 ; PIO 0: REGISTERS BASE ADR
|
||||
PIO1BASE .EQU $6C ; PIO 1: REGISTERS BASE ADR
|
||||
;
|
||||
LPTENABLE .EQU FALSE ; LPT: ENABLE CENTRONICS PRINTER DRIVER (LPT.ASM)
|
||||
LPTENABLE .EQU TRUE ; LPT: ENABLE CENTRONICS PRINTER DRIVER (LPT.ASM)
|
||||
LPTMODE .EQU LPTMODE_SPP ; LPT: DRIVER MODE: LPTMODE_[NONE|SPP|MG014]
|
||||
LPTCNT .EQU 1 ; LPT: NUMBER OF CHIPS TO DETECT (1-2)
|
||||
LPTTRACE .EQU 1 ; LPT: TRACE LEVEL (0=NO,1=ERRORS,2=ALL)
|
||||
LPT0BASE .EQU $E8 ; LPT 0: REGISTERS BASE ADR
|
||||
LPT0BASE .EQU $48 ; LPT 0: REGISTERS BASE ADR
|
||||
LPT1BASE .EQU $EC ; LPT 1: REGISTERS BASE ADR
|
||||
;
|
||||
PPAENABLE .EQU FALSE ; PPA: ENABLE PPA DISK DRIVER (PPA.ASM)
|
||||
|
||||
@@ -90,6 +90,7 @@ PKDOSC .EQU 3000000 ; OSCILLATOR FREQ FOR PKD (IN HZ)
|
||||
H8PENABLE .EQU FALSE ; ENABLES HEATH H8 FRONT PANEL
|
||||
;
|
||||
BOOTCON .EQU 0 ; BOOT CONSOLE DEVICE
|
||||
SECCON .EQU $FF ; SECONDARY CONSOLE DEVICE
|
||||
CRTACT .EQU FALSE ; ACTIVATE CRT (VDU,CVDU,PROPIO,ETC) AT STARTUP
|
||||
VDAEMU .EQU EMUTYP_ANSI ; VDA EMULATION: EMUTYP_[TTY|ANSI]
|
||||
VDAEMU_SERKBD .EQU $FF ; VDA EMULATION: SERIAL KBD UNIT #, OR $FF FOR HW KBD
|
||||
@@ -136,6 +137,7 @@ UARTINTS .EQU FALSE ; UART: INCLUDE INTERRUPT SUPPORT UNDER IM1/2/3
|
||||
UARTCFG .EQU DEFSERCFG | SER_RTS ; UART: LINE CONFIG FOR UART PORTS
|
||||
UARTSBC .EQU FALSE ; UART: AUTO-DETECT SBC/ZETA/DUO ONBOARD UART
|
||||
UARTSBCFORCE .EQU FALSE ; UART: FORCE DETECTION OF SBC UART (FOR SIMH)
|
||||
UARTAUX .EQU FALSE ; UART: AUTO-DETECT AUX UART
|
||||
UARTCAS .EQU FALSE ; UART: AUTO-DETECT ECB CASSETTE UART
|
||||
UARTMFP .EQU FALSE ; UART: AUTO-DETECT MF/PIC UART
|
||||
UART4 .EQU FALSE ; UART: AUTO-DETECT 4UART UART
|
||||
|
||||
@@ -90,6 +90,7 @@ PKDOSC .EQU 3000000 ; OSCILLATOR FREQ FOR PKD (IN HZ)
|
||||
H8PENABLE .EQU FALSE ; ENABLES HEATH H8 FRONT PANEL
|
||||
;
|
||||
BOOTCON .EQU 0 ; BOOT CONSOLE DEVICE
|
||||
SECCON .EQU $FF ; SECONDARY CONSOLE DEVICE
|
||||
CRTACT .EQU FALSE ; ACTIVATE CRT (VDU,CVDU,PROPIO,ETC) AT STARTUP
|
||||
VDAEMU .EQU EMUTYP_ANSI ; VDA EMULATION: EMUTYP_[TTY|ANSI]
|
||||
VDAEMU_SERKBD .EQU $FF ; VDA EMULATION: SERIAL KBD UNIT #, OR $FF FOR HW KBD
|
||||
@@ -136,6 +137,7 @@ UARTINTS .EQU FALSE ; UART: INCLUDE INTERRUPT SUPPORT UNDER IM1/2/3
|
||||
UARTCFG .EQU DEFSERCFG | SER_RTS ; UART: LINE CONFIG FOR UART PORTS
|
||||
UARTSBC .EQU FALSE ; UART: AUTO-DETECT SBC/ZETA/DUO ONBOARD UART
|
||||
UARTSBCFORCE .EQU FALSE ; UART: FORCE DETECTION OF SBC UART (FOR SIMH)
|
||||
UARTAUX .EQU FALSE ; UART: AUTO-DETECT AUX UART
|
||||
UARTCAS .EQU FALSE ; UART: AUTO-DETECT ECB CASSETTE UART
|
||||
UARTMFP .EQU FALSE ; UART: AUTO-DETECT MF/PIC UART
|
||||
UART4 .EQU FALSE ; UART: AUTO-DETECT 4UART UART
|
||||
|
||||
@@ -119,6 +119,7 @@ PKDOSC .EQU 3000000 ; OSCILLATOR FREQ FOR PKD (IN HZ)
|
||||
H8PENABLE .EQU FALSE ; ENABLES HEATH H8 FRONT PANEL
|
||||
;
|
||||
BOOTCON .EQU 0 ; BOOT CONSOLE DEVICE
|
||||
SECCON .EQU $FF ; SECONDARY CONSOLE DEVICE
|
||||
CRTACT .EQU FALSE ; ACTIVATE CRT (VDU,CVDU,PROPIO,ETC) AT STARTUP
|
||||
VDAEMU .EQU EMUTYP_ANSI ; VDA EMULATION: EMUTYP_[TTY|ANSI]
|
||||
VDAEMU_SERKBD .EQU $FF ; VDA EMULATION: SERIAL KBD UNIT #, OR $FF FOR HW KBD
|
||||
@@ -166,6 +167,7 @@ UARTCFG .EQU DEFSERCFG ; UART: LINE CONFIG FOR UART PORTS
|
||||
UARTCASSPD .EQU SER_300_8N1 ; UART: ECB CASSETTE UART DEFAULT SPEED
|
||||
UARTSBC .EQU FALSE ; UART: AUTO-DETECT SBC/ZETA/DUO ONBOARD UART
|
||||
UARTSBCFORCE .EQU FALSE ; UART: FORCE DETECTION OF SBC UART (FOR SIMH)
|
||||
UARTAUX .EQU FALSE ; UART: AUTO-DETECT AUX UART
|
||||
UARTCAS .EQU FALSE ; UART: AUTO-DETECT ECB CASSETTE UART
|
||||
UARTMFP .EQU FALSE ; UART: AUTO-DETECT MF/PIC UART
|
||||
UART4 .EQU FALSE ; UART: AUTO-DETECT 4UART UART
|
||||
|
||||
@@ -85,6 +85,7 @@ PKDOSC .EQU 3000000 ; OSCILLATOR FREQ FOR PKD (IN HZ)
|
||||
H8PENABLE .EQU FALSE ; ENABLES HEATH H8 FRONT PANEL
|
||||
;
|
||||
BOOTCON .EQU 0 ; BOOT CONSOLE DEVICE
|
||||
SECCON .EQU $FF ; SECONDARY CONSOLE DEVICE
|
||||
CRTACT .EQU FALSE ; ACTIVATE CRT (VDU,CVDU,PROPIO,ETC) AT STARTUP
|
||||
VDAEMU .EQU EMUTYP_ANSI ; VDA EMULATION: EMUTYP_[TTY|ANSI]
|
||||
VDAEMU_SERKBD .EQU $FF ; VDA EMULATION: SERIAL KBD UNIT #, OR $FF FOR HW KBD
|
||||
@@ -125,6 +126,7 @@ UARTCFG .EQU DEFSERCFG ; UART: LINE CONFIG FOR UART PORTS
|
||||
UARTCASSPD .EQU SER_300_8N1 ; UART: ECB CASSETTE UART DEFAULT SPEED
|
||||
UARTSBC .EQU TRUE ; UART: AUTO-DETECT SBC/ZETA/DUO ONBOARD UART
|
||||
UARTSBCFORCE .EQU FALSE ; UART: FORCE DETECTION OF SBC UART (FOR SIMH)
|
||||
UARTAUX .EQU FALSE ; UART: AUTO-DETECT AUX UART
|
||||
UARTCAS .EQU FALSE ; UART: AUTO-DETECT ECB CASSETTE UART
|
||||
UARTMFP .EQU FALSE ; UART: AUTO-DETECT MF/PIC UART
|
||||
UART4 .EQU FALSE ; UART: AUTO-DETECT 4UART UART
|
||||
|
||||
@@ -90,6 +90,7 @@ PKDOSC .EQU 3000000 ; OSCILLATOR FREQ FOR PKD (IN HZ)
|
||||
H8PENABLE .EQU FALSE ; ENABLES HEATH H8 FRONT PANEL
|
||||
;
|
||||
BOOTCON .EQU 0 ; BOOT CONSOLE DEVICE
|
||||
SECCON .EQU $FF ; SECONDARY CONSOLE DEVICE
|
||||
CRTACT .EQU FALSE ; ACTIVATE CRT (VDU,CVDU,PROPIO,ETC) AT STARTUP
|
||||
VDAEMU .EQU EMUTYP_ANSI ; VDA EMULATION: EMUTYP_[TTY|ANSI]
|
||||
VDAEMU_SERKBD .EQU $FF ; VDA EMULATION: SERIAL KBD UNIT #, OR $FF FOR HW KBD
|
||||
@@ -130,6 +131,7 @@ UARTCFG .EQU DEFSERCFG ; UART: LINE CONFIG FOR UART PORTS
|
||||
UARTCASSPD .EQU SER_300_8N1 ; UART: ECB CASSETTE UART DEFAULT SPEED
|
||||
UARTSBC .EQU FALSE ; UART: AUTO-DETECT SBC/ZETA/DUO ONBOARD UART
|
||||
UARTSBCFORCE .EQU FALSE ; UART: FORCE DETECTION OF SBC UART (FOR SIMH)
|
||||
UARTAUX .EQU FALSE ; UART: AUTO-DETECT AUX UART
|
||||
UARTCAS .EQU TRUE ; UART: AUTO-DETECT ECB CASSETTE UART
|
||||
UARTMFP .EQU FALSE ; UART: AUTO-DETECT MF/PIC UART
|
||||
UART4 .EQU TRUE ; UART: AUTO-DETECT 4UART UART
|
||||
|
||||
@@ -92,6 +92,7 @@ PKDOSC .EQU 3000000 ; OSCILLATOR FREQ FOR PKD (IN HZ)
|
||||
H8PENABLE .EQU FALSE ; ENABLES HEATH H8 FRONT PANEL
|
||||
;
|
||||
BOOTCON .EQU 0 ; BOOT CONSOLE DEVICE
|
||||
SECCON .EQU $FF ; SECONDARY CONSOLE DEVICE
|
||||
CRTACT .EQU FALSE ; ACTIVATE CRT (VDU,CVDU,PROPIO,ETC) AT STARTUP
|
||||
VDAEMU .EQU EMUTYP_ANSI ; VDA EMULATION: EMUTYP_[TTY|ANSI]
|
||||
VDAEMU_SERKBD .EQU $FF ; VDA EMULATION: SERIAL KBD UNIT #, OR $FF FOR HW KBD
|
||||
@@ -132,6 +133,7 @@ UARTCFG .EQU DEFSERCFG ; UART: LINE CONFIG FOR UART PORTS
|
||||
UARTCASSPD .EQU SER_300_8N1 ; UART: ECB CASSETTE UART DEFAULT SPEED
|
||||
UARTSBC .EQU FALSE ; UART: AUTO-DETECT SBC/ZETA/DUO ONBOARD UART
|
||||
UARTSBCFORCE .EQU FALSE ; UART: FORCE DETECTION OF SBC UART (FOR SIMH)
|
||||
UARTAUX .EQU FALSE ; UART: AUTO-DETECT AUX UART
|
||||
UARTCAS .EQU TRUE ; UART: AUTO-DETECT ECB CASSETTE UART
|
||||
UARTMFP .EQU FALSE ; UART: AUTO-DETECT MF/PIC UART
|
||||
UART4 .EQU TRUE ; UART: AUTO-DETECT 4UART UART
|
||||
|
||||
@@ -96,6 +96,7 @@ PKDOSC .EQU 3000000 ; OSCILLATOR FREQ FOR PKD (IN HZ)
|
||||
H8PENABLE .EQU FALSE ; ENABLES HEATH H8 FRONT PANEL
|
||||
;
|
||||
BOOTCON .EQU 0 ; BOOT CONSOLE DEVICE
|
||||
SECCON .EQU $FF ; SECONDARY CONSOLE DEVICE
|
||||
CRTACT .EQU FALSE ; ACTIVATE CRT (VDU,CVDU,PROPIO,ETC) AT STARTUP
|
||||
VDAEMU .EQU EMUTYP_ANSI ; VDA EMULATION: EMUTYP_[TTY|ANSI]
|
||||
VDAEMU_SERKBD .EQU $FF ; VDA EMULATION: SERIAL KBD UNIT #, OR $FF FOR HW KBD
|
||||
@@ -142,6 +143,7 @@ UARTINTS .EQU FALSE ; UART: INCLUDE INTERRUPT SUPPORT UNDER IM1/2/3
|
||||
UARTCFG .EQU DEFSERCFG | SER_RTS ; UART: LINE CONFIG FOR UART PORTS
|
||||
UARTSBC .EQU FALSE ; UART: AUTO-DETECT SBC/ZETA/DUO ONBOARD UART
|
||||
UARTSBCFORCE .EQU FALSE ; UART: FORCE DETECTION OF SBC UART (FOR SIMH)
|
||||
UARTAUX .EQU FALSE ; UART: AUTO-DETECT AUX UART
|
||||
UARTCAS .EQU FALSE ; UART: AUTO-DETECT ECB CASSETTE UART
|
||||
UARTMFP .EQU FALSE ; UART: AUTO-DETECT MF/PIC UART
|
||||
UART4 .EQU FALSE ; UART: AUTO-DETECT 4UART UART
|
||||
|
||||
@@ -90,6 +90,7 @@ PKDOSC .EQU 3000000 ; OSCILLATOR FREQ FOR PKD (IN HZ)
|
||||
H8PENABLE .EQU FALSE ; ENABLES HEATH H8 FRONT PANEL
|
||||
;
|
||||
BOOTCON .EQU 0 ; BOOT CONSOLE DEVICE
|
||||
SECCON .EQU $FF ; SECONDARY CONSOLE DEVICE
|
||||
CRTACT .EQU FALSE ; ACTIVATE CRT (VDU,CVDU,PROPIO,ETC) AT STARTUP
|
||||
VDAEMU .EQU EMUTYP_ANSI ; VDA EMULATION: EMUTYP_[TTY|ANSI]
|
||||
VDAEMU_SERKBD .EQU $FF ; VDA EMULATION: SERIAL KBD UNIT #, OR $FF FOR HW KBD
|
||||
@@ -136,6 +137,7 @@ UARTINTS .EQU FALSE ; UART: INCLUDE INTERRUPT SUPPORT UNDER IM1/2/3
|
||||
UARTCFG .EQU DEFSERCFG | SER_RTS ; UART: LINE CONFIG FOR UART PORTS
|
||||
UARTSBC .EQU FALSE ; UART: AUTO-DETECT SBC/ZETA/DUO ONBOARD UART
|
||||
UARTSBCFORCE .EQU FALSE ; UART: FORCE DETECTION OF SBC UART (FOR SIMH)
|
||||
UARTAUX .EQU FALSE ; UART: AUTO-DETECT AUX UART
|
||||
UARTCAS .EQU FALSE ; UART: AUTO-DETECT ECB CASSETTE UART
|
||||
UARTMFP .EQU FALSE ; UART: AUTO-DETECT MF/PIC UART
|
||||
UART4 .EQU FALSE ; UART: AUTO-DETECT 4UART UART
|
||||
|
||||
@@ -90,6 +90,7 @@ PKDOSC .EQU 3000000 ; OSCILLATOR FREQ FOR PKD (IN HZ)
|
||||
H8PENABLE .EQU FALSE ; ENABLES HEATH H8 FRONT PANEL
|
||||
;
|
||||
BOOTCON .EQU 0 ; BOOT CONSOLE DEVICE
|
||||
SECCON .EQU $FF ; SECONDARY CONSOLE DEVICE
|
||||
CRTACT .EQU FALSE ; ACTIVATE CRT (VDU,CVDU,PROPIO,ETC) AT STARTUP
|
||||
VDAEMU .EQU EMUTYP_ANSI ; VDA EMULATION: EMUTYP_[TTY|ANSI]
|
||||
VDAEMU_SERKBD .EQU $FF ; VDA EMULATION: SERIAL KBD UNIT #, OR $FF FOR HW KBD
|
||||
@@ -136,6 +137,7 @@ UARTINTS .EQU FALSE ; UART: INCLUDE INTERRUPT SUPPORT UNDER IM1/2/3
|
||||
UARTCFG .EQU DEFSERCFG | SER_RTS ; UART: LINE CONFIG FOR UART PORTS
|
||||
UARTSBC .EQU FALSE ; UART: AUTO-DETECT SBC/ZETA/DUO ONBOARD UART
|
||||
UARTSBCFORCE .EQU FALSE ; UART: FORCE DETECTION OF SBC UART (FOR SIMH)
|
||||
UARTAUX .EQU FALSE ; UART: AUTO-DETECT AUX UART
|
||||
UARTCAS .EQU FALSE ; UART: AUTO-DETECT ECB CASSETTE UART
|
||||
UARTMFP .EQU FALSE ; UART: AUTO-DETECT MF/PIC UART
|
||||
UART4 .EQU FALSE ; UART: AUTO-DETECT 4UART UART
|
||||
|
||||
@@ -90,6 +90,7 @@ PKDOSC .EQU 3000000 ; OSCILLATOR FREQ FOR PKD (IN HZ)
|
||||
H8PENABLE .EQU FALSE ; ENABLES HEATH H8 FRONT PANEL
|
||||
;
|
||||
BOOTCON .EQU 0 ; BOOT CONSOLE DEVICE
|
||||
SECCON .EQU $FF ; SECONDARY CONSOLE DEVICE
|
||||
CRTACT .EQU FALSE ; ACTIVATE CRT (VDU,CVDU,PROPIO,ETC) AT STARTUP
|
||||
VDAEMU .EQU EMUTYP_ANSI ; VDA EMULATION: EMUTYP_[TTY|ANSI]
|
||||
VDAEMU_SERKBD .EQU $FF ; VDA EMULATION: SERIAL KBD UNIT #, OR $FF FOR HW KBD
|
||||
@@ -130,6 +131,7 @@ UARTCFG .EQU DEFSERCFG ; UART: LINE CONFIG FOR UART PORTS
|
||||
UARTCASSPD .EQU SER_300_8N1 ; UART: ECB CASSETTE UART DEFAULT SPEED
|
||||
UARTSBC .EQU FALSE ; UART: AUTO-DETECT SBC/ZETA/DUO ONBOARD UART
|
||||
UARTSBCFORCE .EQU FALSE ; UART: FORCE DETECTION OF SBC UART (FOR SIMH)
|
||||
UARTAUX .EQU FALSE ; UART: AUTO-DETECT AUX UART
|
||||
UARTCAS .EQU FALSE ; UART: AUTO-DETECT ECB CASSETTE UART
|
||||
UARTMFP .EQU FALSE ; UART: AUTO-DETECT MF/PIC UART
|
||||
UART4 .EQU FALSE ; UART: AUTO-DETECT 4UART UART
|
||||
|
||||
@@ -90,6 +90,7 @@ PKDOSC .EQU 3000000 ; OSCILLATOR FREQ FOR PKD (IN HZ)
|
||||
H8PENABLE .EQU FALSE ; ENABLES HEATH H8 FRONT PANEL
|
||||
;
|
||||
BOOTCON .EQU 0 ; BOOT CONSOLE DEVICE
|
||||
SECCON .EQU $FF ; SECONDARY CONSOLE DEVICE
|
||||
CRTACT .EQU FALSE ; ACTIVATE CRT (VDU,CVDU,PROPIO,ETC) AT STARTUP
|
||||
VDAEMU .EQU EMUTYP_ANSI ; VDA EMULATION: EMUTYP_[TTY|ANSI]
|
||||
VDAEMU_SERKBD .EQU $FF ; VDA EMULATION: SERIAL KBD UNIT #, OR $FF FOR HW KBD
|
||||
@@ -136,6 +137,7 @@ UARTINTS .EQU FALSE ; UART: INCLUDE INTERRUPT SUPPORT UNDER IM1/2/3
|
||||
UARTCFG .EQU DEFSERCFG | SER_RTS ; UART: LINE CONFIG FOR UART PORTS
|
||||
UARTSBC .EQU FALSE ; UART: AUTO-DETECT SBC/ZETA/DUO ONBOARD UART
|
||||
UARTSBCFORCE .EQU FALSE ; UART: FORCE DETECTION OF SBC UART (FOR SIMH)
|
||||
UARTAUX .EQU FALSE ; UART: AUTO-DETECT AUX UART
|
||||
UARTCAS .EQU FALSE ; UART: AUTO-DETECT ECB CASSETTE UART
|
||||
UARTMFP .EQU FALSE ; UART: AUTO-DETECT MF/PIC UART
|
||||
UART4 .EQU FALSE ; UART: AUTO-DETECT 4UART UART
|
||||
|
||||
@@ -85,6 +85,7 @@ PKDOSC .EQU 3000000 ; OSCILLATOR FREQ FOR PKD (IN HZ)
|
||||
H8PENABLE .EQU FALSE ; ENABLES HEATH H8 FRONT PANEL
|
||||
;
|
||||
BOOTCON .EQU 0 ; BOOT CONSOLE DEVICE
|
||||
SECCON .EQU $FF ; SECONDARY CONSOLE DEVICE
|
||||
CRTACT .EQU FALSE ; ACTIVATE CRT (VDU,CVDU,PROPIO,ETC) AT STARTUP
|
||||
VDAEMU .EQU EMUTYP_ANSI ; VDA EMULATION: EMUTYP_[TTY|ANSI]
|
||||
VDAEMU_SERKBD .EQU $FF ; VDA EMULATION: SERIAL KBD UNIT #, OR $FF FOR HW KBD
|
||||
@@ -125,6 +126,7 @@ UARTCFG .EQU DEFSERCFG ; UART: LINE CONFIG FOR UART PORTS
|
||||
UARTCASSPD .EQU SER_300_8N1 ; UART: ECB CASSETTE UART DEFAULT SPEED
|
||||
UARTSBC .EQU TRUE ; UART: AUTO-DETECT SBC/ZETA/DUO ONBOARD UART
|
||||
UARTSBCFORCE .EQU FALSE ; UART: FORCE DETECTION OF SBC UART (FOR SIMH)
|
||||
UARTAUX .EQU FALSE ; UART: AUTO-DETECT AUX UART
|
||||
UARTCAS .EQU TRUE ; UART: AUTO-DETECT ECB CASSETTE UART
|
||||
UARTMFP .EQU TRUE ; UART: AUTO-DETECT MF/PIC UART
|
||||
UART4 .EQU TRUE ; UART: AUTO-DETECT 4UART UART
|
||||
|
||||
@@ -90,6 +90,7 @@ PKDOSC .EQU 3000000 ; OSCILLATOR FREQ FOR PKD (IN HZ)
|
||||
H8PENABLE .EQU FALSE ; ENABLES HEATH H8 FRONT PANEL
|
||||
;
|
||||
BOOTCON .EQU 0 ; BOOT CONSOLE DEVICE
|
||||
SECCON .EQU $FF ; SECONDARY CONSOLE DEVICE
|
||||
CRTACT .EQU FALSE ; ACTIVATE CRT (VDU,CVDU,PROPIO,ETC) AT STARTUP
|
||||
VDAEMU .EQU EMUTYP_ANSI ; VDA EMULATION: EMUTYP_[TTY|ANSI]
|
||||
VDAEMU_SERKBD .EQU $FF ; VDA EMULATION: SERIAL KBD UNIT #, OR $FF FOR HW KBD
|
||||
@@ -135,6 +136,7 @@ UARTOSC .EQU 1843200 ; UART: OSC FREQUENCY IN MHZ
|
||||
UARTINTS .EQU FALSE ; UART: INCLUDE INTERRUPT SUPPORT UNDER IM1/2/3
|
||||
UARTCFG .EQU DEFSERCFG | SER_RTS ; UART: LINE CONFIG FOR UART PORTS
|
||||
UARTSBC .EQU FALSE ; UART: AUTO-DETECT SBC/ZETA/DUO ONBOARD UART
|
||||
UARTAUX .EQU FALSE ; UART: AUTO-DETECT AUX UART
|
||||
UARTSBCFORCE .EQU FALSE ; UART: FORCE DETECTION OF SBC UART (FOR SIMH)
|
||||
UARTCAS .EQU FALSE ; UART: AUTO-DETECT ECB CASSETTE UART
|
||||
UARTMFP .EQU FALSE ; UART: AUTO-DETECT MF/PIC UART
|
||||
|
||||
@@ -88,6 +88,7 @@ PKDOSC .EQU 3000000 ; OSCILLATOR FREQ FOR PKD (IN HZ)
|
||||
H8PENABLE .EQU FALSE ; ENABLES HEATH H8 FRONT PANEL
|
||||
;
|
||||
BOOTCON .EQU 0 ; BOOT CONSOLE DEVICE
|
||||
SECCON .EQU $FF ; SECONDARY CONSOLE DEVICE
|
||||
CRTACT .EQU FALSE ; ACTIVATE CRT (VDU,CVDU,PROPIO,ETC) AT STARTUP
|
||||
VDAEMU .EQU EMUTYP_ANSI ; VDA EMULATION: EMUTYP_[TTY|ANSI]
|
||||
VDAEMU_SERKBD .EQU $FF ; VDA EMULATION: SERIAL KBD UNIT #, OR $FF FOR HW KBD
|
||||
@@ -122,6 +123,7 @@ UARTINTS .EQU FALSE ; UART: INCLUDE INTERRUPT SUPPORT UNDER IM1/2/3
|
||||
UARTCFG .EQU DEFSERCFG ; UART: LINE CONFIG FOR UART PORTS
|
||||
UARTCASSPD .EQU SER_300_8N1 ; UART: ECB CASSETTE UART DEFAULT SPEED
|
||||
UARTSBC .EQU TRUE ; UART: AUTO-DETECT SBC/ZETA/DUO ONBOARD UART
|
||||
UARTAUX .EQU FALSE ; UART: AUTO-DETECT AUX UART
|
||||
UARTSBCFORCE .EQU FALSE ; UART: FORCE DETECTION OF SBC UART (FOR SIMH)
|
||||
UARTCAS .EQU FALSE ; UART: AUTO-DETECT ECB CASSETTE UART
|
||||
UARTMFP .EQU FALSE ; UART: AUTO-DETECT MF/PIC UART
|
||||
|
||||
@@ -77,6 +77,7 @@ PKDOSC .EQU 3000000 ; OSCILLATOR FREQ FOR PKD (IN HZ)
|
||||
H8PENABLE .EQU FALSE ; ENABLES HEATH H8 FRONT PANEL
|
||||
;
|
||||
BOOTCON .EQU 0 ; BOOT CONSOLE DEVICE
|
||||
SECCON .EQU $FF ; SECONDARY CONSOLE DEVICE
|
||||
CRTACT .EQU FALSE ; ACTIVATE CRT (VDU,CVDU,PROPIO,ETC) AT STARTUP
|
||||
VDAEMU .EQU EMUTYP_ANSI ; VDA EMULATION: EMUTYP_[TTY|ANSI]
|
||||
VDAEMU_SERKBD .EQU $FF ; VDA EMULATION: SERIAL KBD UNIT #, OR $FF FOR HW KBD
|
||||
@@ -112,6 +113,7 @@ UARTCFG .EQU DEFSERCFG ; UART: LINE CONFIG FOR UART PORTS
|
||||
UARTCASSPD .EQU SER_300_8N1 ; UART: ECB CASSETTE UART DEFAULT SPEED
|
||||
UARTSBC .EQU TRUE ; UART: AUTO-DETECT SBC/ZETA ONBOARD UART
|
||||
UARTSBCFORCE .EQU FALSE ; UART: FORCE DETECTION OF SBC UART (FOR SIMH)
|
||||
UARTAUX .EQU FALSE ; UART: AUTO-DETECT AUX UART
|
||||
UARTCAS .EQU FALSE ; UART: AUTO-DETECT ECB CASSETTE UART
|
||||
UARTMFP .EQU FALSE ; UART: AUTO-DETECT MF/PIC UART
|
||||
UART4 .EQU FALSE ; UART: AUTO-DETECT 4UART UART
|
||||
|
||||
@@ -88,6 +88,7 @@ PKDOSC .EQU 3000000 ; OSCILLATOR FREQ FOR PKD (IN HZ)
|
||||
H8PENABLE .EQU FALSE ; ENABLES HEATH H8 FRONT PANEL
|
||||
;
|
||||
BOOTCON .EQU 0 ; BOOT CONSOLE DEVICE
|
||||
SECCON .EQU $FF ; SECONDARY CONSOLE DEVICE
|
||||
CRTACT .EQU FALSE ; ACTIVATE CRT (VDU,CVDU,PROPIO,ETC) AT STARTUP
|
||||
VDAEMU .EQU EMUTYP_ANSI ; VDA EMULATION: EMUTYP_[TTY|ANSI]
|
||||
VDAEMU_SERKBD .EQU $FF ; VDA EMULATION: SERIAL KBD UNIT #, OR $FF FOR HW KBD
|
||||
@@ -123,6 +124,7 @@ UARTCFG .EQU DEFSERCFG ; UART: LINE CONFIG FOR UART PORTS
|
||||
UARTCASSPD .EQU SER_300_8N1 ; UART: ECB CASSETTE UART DEFAULT SPEED
|
||||
UARTSBC .EQU TRUE ; UART: AUTO-DETECT SBC/ZETA/DUO ONBOARD UART
|
||||
UARTSBCFORCE .EQU FALSE ; UART: FORCE DETECTION OF SBC UART (FOR SIMH)
|
||||
UARTAUX .EQU FALSE ; UART: AUTO-DETECT AUX UART
|
||||
UARTCAS .EQU FALSE ; UART: AUTO-DETECT ECB CASSETTE UART
|
||||
UARTMFP .EQU FALSE ; UART: AUTO-DETECT MF/PIC UART
|
||||
UART4 .EQU FALSE ; UART: AUTO-DETECT 4UART UART
|
||||
|
||||
@@ -18,9 +18,8 @@
|
||||
; added to the RESET routine when using CH376.
|
||||
;
|
||||
; TODO:
|
||||
; - Implement auto-recovery on error status.
|
||||
;
|
||||
CHUSB_FASTIO .EQU TRUE ; USE INIR/OTIR?
|
||||
; - Implement auto-recovery on error status?
|
||||
; - !!! Move CH_MODE to config variable !!!
|
||||
;
|
||||
; PORT OFFSETS FROM BASE PORT
|
||||
;
|
||||
@@ -33,6 +32,12 @@ CHTYP_NONE .EQU 0 ; NONE
|
||||
CHTYP_375 .EQU 1 ; CH375
|
||||
CHTYP_376 .EQU 2 ; CH376
|
||||
;
|
||||
; CH MODE MANAGEMENT
|
||||
;
|
||||
CH_MODE_UNK .EQU 0 ; CURRENT MODE UNKNOWN
|
||||
CH_MODE_USB .EQU 1 ; CURRENT MODE = USB
|
||||
CH_MODE_SD .EQU 2 ; CURRENT MODE = SD
|
||||
;
|
||||
; CH375/376 COMMANDS
|
||||
;
|
||||
CH_CMD_VER .EQU $01 ; GET IC VER
|
||||
@@ -41,6 +46,7 @@ CH_CMD_EXIST .EQU $06 ; CHECK EXISTS
|
||||
CH_CMD_MAXLUN .EQU $0A ; GET MAX LUN NUMBER
|
||||
CH_CMD_PKTSEC .EQU $0B ; SET PACKETS PER SECTOR
|
||||
CH_CMD_SETRETRY .EQU $0B ; SET RETRIES
|
||||
CH_CMD_FILESIZE .EQU $0C ; GET FILE SIZE (376)
|
||||
CH_CMD_MODE .EQU $15 ; SET USB MODE
|
||||
CH_CMD_TSTCON .EQU $16 ; TEST CONNECT
|
||||
CH_CMD_ABRTNAK .EQU $17 ; ABORT DEVICE NAK RETRIES
|
||||
@@ -49,7 +55,16 @@ CH_CMD_RD6 .EQU $27 ; READ USB DATA (375 & 376)
|
||||
CH_CMD_RD5 .EQU $28 ; READ USB DATA (375)
|
||||
CH_CMD_WR5 .EQU $2B ; WRITE USB DATA (375)
|
||||
CH_CMD_WR6 .EQU $2C ; WRITE USB DATA (376)
|
||||
CH_CMD_WRREQDAT .EQU $2D ; WRITE REQUESTED DATA (376)
|
||||
CH_CMD_SET_FN .EQU $2F ; SET FILENAME (376)
|
||||
CH_CMD_DSKMNT .EQU $31 ; DISK MOUNT
|
||||
CH_CMD_FOPEN .EQU $32 ; FILE OPEN (376)
|
||||
CH_CMD_FCREAT .EQU $34 ; FILE CREATE (376)
|
||||
CH_CMD_BYTE_LOC .EQU $39 ; BYTE LOCATE
|
||||
CH_CMD_BYTERD .EQU $3A ; BYTE READ
|
||||
CH_CMD_BYTERDGO .EQU $3B ; BYTE READ GO
|
||||
CH_CMD_BYTEWR .EQU $3C ; BYTE WRITE
|
||||
CH_CMD_BYTEWRGO .EQU $3D ; BYTE WRITE GO
|
||||
CH_CMD_DSKCAP .EQU $3E ; DISK CAPACITY
|
||||
CH_CMD_AUTOSET .EQU $4D ; USB AUTO SETUP
|
||||
CH_CMD_DSKINIT .EQU $51 ; DISK INIT
|
||||
@@ -129,6 +144,8 @@ CH_INIT2:
|
||||
LD A,(IY+CH_IOBASE) ; GET IO BASE ADDRES
|
||||
CALL PRTHEXBYTE ; DISPLAY IT
|
||||
;
|
||||
XOR A ; UNKNOWN MODE
|
||||
LD (CH_MODE),A ; SAVE IT
|
||||
;CALL CH_FLUSH ; FLUSH DEVICE OUTPUT QUEUE
|
||||
CALL CH_RESET ; FULL CH37X RESET
|
||||
CALL CH_DETECT ; DETECT CHIP PRESENCE
|
||||
@@ -347,18 +364,63 @@ CH_GETVER:
|
||||
CALL CH_RD ; GET VERSION BYTE
|
||||
RET ; DONE
|
||||
;
|
||||
; SET MODE TO VALUE IN A
|
||||
; AVOID CHANGING MODES IF CURRENT MODE = NEW MODE
|
||||
; THE CH376 DOES NOT SEEM TO MAINTAIN SEPARATE OPERATING CONTEXTS FOR
|
||||
; THE USB AND SD DEVICES. IF BOTH ARE IN OPERATION, THEN A MODE
|
||||
; SWITCH REQUIRES A COMPLETE REINITIALIZATION OF THE REQUESTED
|
||||
; DEVICE.
|
||||
;
|
||||
CH_SETMODE:
|
||||
PUSH BC ; SAVE BC
|
||||
PUSH DE ; SAVE DE
|
||||
PUSH HL ; SAVE HL
|
||||
;PRTS("\r\nSETMODE:$") ; *DEBUG*
|
||||
LD L,A ; SAVE REQUESTED MODE
|
||||
LD A,(CH_MODE) ; GET CURRENT MODE
|
||||
;CALL PC_SPACE ; *DEBUG*
|
||||
;CALL PRTHEXBYTE ; *DEBUG*
|
||||
CP L ; COMPARE
|
||||
JR Z,CH_SETMODE_Z ; IF EQUAL, DONE
|
||||
;
|
||||
; NEED TO CHANGE MODES
|
||||
LD A,L ; GET REQUESTED MODE
|
||||
CP CH_MODE_USB ; USB?
|
||||
JR Z,CH_SETMODE_USB ; IF SO, DO IT
|
||||
CP CH_MODE_SD ; SD?
|
||||
JR Z,CH_SETMODE_SD ; IF SO, DO IT
|
||||
OR $FF ; SIGNAL ERROR
|
||||
JR CH_SETMODE_Z ; BAIL OUT
|
||||
;
|
||||
CH_SETMODE_USB:
|
||||
CALL CHUSB_RESET ; FULL USB STACK RESET
|
||||
JR CH_SETMODE_Z ; MOVE ON
|
||||
;
|
||||
CH_SETMODE_SD:
|
||||
CALL CHSD_RESET ; FULL SD STACK RESET
|
||||
JR CH_SETMODE_Z ; MOVE ON
|
||||
;
|
||||
CH_SETMODE_Z:
|
||||
POP HL ; RECOVER HL
|
||||
POP DE ; RECOVER DE
|
||||
POP BC ; RECOVER BC
|
||||
RET ; DONE
|
||||
;
|
||||
;
|
||||
CH_STR_NOHW .TEXT " NOT PRESENT$"
|
||||
CH_STR_UPGRADE .TEXT " !!!UPGRADE REQUIRED!!!$"
|
||||
;
|
||||
CH_STR_375 .TEXT "CH375$"
|
||||
CH_STR_376 .TEXT "CH376$"
|
||||
CH_MODE .DB CH_MODE_UNK
|
||||
;
|
||||
CH_STR_NOHW .TEXT " NOT PRESENT$"
|
||||
;
|
||||
CH_STR_375 .TEXT "CH375$"
|
||||
CH_STR_376 .TEXT "CH376$"
|
||||
;
|
||||
;==================================================================================================
|
||||
; CH375/376 USB SUB-DRIVER
|
||||
;==================================================================================================
|
||||
;
|
||||
CHUSB_FASTIO .EQU TRUE ; USE INIR/OTIR?
|
||||
;
|
||||
; CHUSB DEVICE STATUS
|
||||
;
|
||||
CHUSB_STOK .EQU 0
|
||||
@@ -368,7 +430,7 @@ CHUSB_STIOERR .EQU -3
|
||||
CHUSB_STTO .EQU -4
|
||||
CHUSB_STNOTSUP .EQU -5
|
||||
;
|
||||
; CH DEVICE CONFIGURATION
|
||||
; CHUSB DEVICE CONFIGURATION
|
||||
;
|
||||
CHUSB_CFGSIZ .EQU 12 ; SIZE OF USB CFG TBL ENTRIES
|
||||
;
|
||||
@@ -481,6 +543,10 @@ CHUSB_DEFMED:
|
||||
;
|
||||
;
|
||||
CHUSB_READ:
|
||||
LD A,CH_MODE_USB ; REQUEST USB MODE
|
||||
CALL CH_SETMODE ; DO IT
|
||||
JP NZ,CHUSB_CMDERR ; HANDLE ERROR
|
||||
;
|
||||
CALL HB_DSKREAD ; HOOK HBIOS DISK READ SUPERVISOR
|
||||
LD (CHUSB_DSKBUF),HL ; SAVE DISK BUFFER ADDRESS
|
||||
LD A,CH_CMD_DSKRD ; DISK READ COMMAND
|
||||
@@ -542,6 +608,10 @@ CHUSB_READ2:
|
||||
;
|
||||
;
|
||||
CHUSB_WRITE:
|
||||
LD A,CH_MODE_USB ; REQUEST USB MODE
|
||||
CALL CH_SETMODE ; DO IT
|
||||
JP NZ,CHUSB_CMDERR ; HANDLE ERROR
|
||||
;
|
||||
CALL HB_DSKWRITE ; HOOK HBIOS DISK WRITE SUPERVISOR
|
||||
LD (CHUSB_DSKBUF),HL ; SAVE DISK BUFFER ADDRESS
|
||||
LD A,CH_CMD_DSKWR ; DISK READ COMMAND
|
||||
@@ -631,7 +701,7 @@ CHUSB_STATUS:
|
||||
; RESET THE INTERFACE AND REDISCOVER MEDIA
|
||||
;
|
||||
CHUSB_RESET:
|
||||
;PRTS("\n\rRESET:$") ; *DEBUG*
|
||||
;PRTS("\n\rRES USB:$") ; *DEBUG*
|
||||
;CALL CH_FLUSH ; DISCARD ANY GARBAGE
|
||||
;CALL CH_RESET ; FULL CH37X RESET
|
||||
;
|
||||
@@ -656,6 +726,9 @@ CHUSB_RESET:
|
||||
;CALL PC_SPACE ; *DEBUG*
|
||||
;CALL PRTHEXBYTE ; *DEBUG*
|
||||
CALL CH_NAP ; SMALL WAIT
|
||||
;
|
||||
LD A,CH_MODE_USB ; WE ARE NOW IN USB MODE
|
||||
LD (CH_MODE),A ; SAVE IT
|
||||
;
|
||||
; INITIALIZE DISK
|
||||
LD B,24 ; TRY A FEW TIMES
|
||||
@@ -671,29 +744,28 @@ CHUSB_RESET1:
|
||||
;CALL PC_SPACE ; *DEBUG*
|
||||
;CALL PRTHEXBYTE ; *DEBUG*
|
||||
CP $14 ; SUCCESS?
|
||||
JR Z,CHUSB_RESET2 ; IF SO, CONTINUE
|
||||
;JR Z,CHUSB_RESET1A ; IF SO, CHECK READY
|
||||
JR Z,CHUSB_RESET1A ; IF SO, CHECK READY
|
||||
CP $16 ; NO MEDIA
|
||||
JP Z,CHUSB_NOMEDIA ; HANDLE IT
|
||||
CALL CH_NAP ; SMALL DELAY
|
||||
DJNZ CHUSB_RESET1 ; LOOP AS NEEDED
|
||||
JP CHUSB_TO ; HANDLE TIMEOUT
|
||||
;;;;
|
||||
;;;CHUSB_RESET1A:
|
||||
;;; CALL CHUSB_DSKRES ; DISK RESET
|
||||
;;; CP $14 ; GOOD?
|
||||
;;; JR Z,CHUSB_RESET2
|
||||
;;; CALL CHUSB_DSKRDY ; CHECK IF DISK READY
|
||||
;;; CP $14 ; GOOD?
|
||||
;;; JR Z,CHUSB_RESET2 ; IF SO, MOVE ON
|
||||
;;; DJNZ CHUSB_RESET1 ; KEEP TRYING
|
||||
;
|
||||
CHUSB_RESET1A:
|
||||
;CALL CHUSB_DSKRES ; DISK RESET
|
||||
;CP $14 ; GOOD?
|
||||
;JR Z,CHUSB_RESET2
|
||||
;CALL CHUSB_DSKRDY ; CHECK IF DISK READY
|
||||
;CP $14 ; GOOD?
|
||||
;JR Z,CHUSB_RESET2 ; IF SO, MOVE ON
|
||||
;DJNZ CHUSB_RESET1 ; KEEP TRYING
|
||||
;
|
||||
CHUSB_RESET2:
|
||||
; USE OF CH376 DISK_MOUNT COMMAND SEEMS TO IMPROVE
|
||||
; COMPATIBILITY WITH SOME OLDER USB THUMBDRIVES.
|
||||
LD A,(IY+CH_TYPE) ; CH37X TYPE?
|
||||
CP CHTYP_376 ; IS CH376?
|
||||
CALL Z,CHUSB_DSKMNT ; IF SO, ISSUE MOUNT
|
||||
CALL Z,CHUSB_DSKMNT ; IF SO, TRY MOUNT, IGNORE ERRS
|
||||
;CALL CHUSB_AUTOSET ; *DEBUG*
|
||||
;CALL CHUSB_TSTCON ; *DEBUG*
|
||||
;CALL CHUSB_MAXLUN ; *DEBUG*
|
||||
@@ -714,7 +786,7 @@ CHUSB_RESET2:
|
||||
CHUSB_DEVICE:
|
||||
LD D,DIODEV_CHUSB ; D := DEVICE TYPE
|
||||
LD E,(IY+CH_DEV) ; E := PHYSICAL DEVICE NUMBER
|
||||
LD C,%01110011 ; USB HARD DISK ATTRIBUTES
|
||||
LD C,%00110011 ; USB HARD DISK ATTRIBUTES
|
||||
LD H,(IY+CH_TYPE) ; H := MODE
|
||||
LD L,(IY+CH_IOBASE) ; L := BASE I/O ADDRESS
|
||||
XOR A ; SIGNAL SUCCESS
|
||||
@@ -791,28 +863,34 @@ CHUSB_DSKMNT:
|
||||
;CALL PRTHEXBYTE ; *DEBUG*
|
||||
CP $14 ; SUCCESS?
|
||||
RET NZ ; ABORT IF NOT
|
||||
;
|
||||
#IF FALSE
|
||||
CALL CH_CMD_RD ; SEND READ COMMAND
|
||||
CALL CH_RD ; GET LENGTH
|
||||
;CALL PC_SPACE ; *DEBUG*
|
||||
;CALL PRTHEXBYTE ; *DEBUG*
|
||||
LD B,A ; LOOP COUNTER
|
||||
LD HL,HB_WRKBUF ; USE WORK BUFFER FOR DATA
|
||||
DSKMNT1:
|
||||
CHUSB_DSKMNT1:
|
||||
CALL CH_RD ; GET A BYTE
|
||||
LD (HL),A ; SAVE IT
|
||||
INC HL ; BUMP BUF PTR
|
||||
DJNZ DSKMNT1 ; LOOP FOR ALL DATA
|
||||
DJNZ CHUSB_DSKMNT1 ; LOOP FOR ALL DATA
|
||||
;
|
||||
;LD DE,HB_WRKBUF ; *DEBUG*
|
||||
;CALL DUMP_BUFFER ; *DEBUG*
|
||||
;
|
||||
;CALL CHUSB_PRTPREFIX ; PRINT DEVICE PREFIX
|
||||
;LD HL,HB_WRKBUF + 8
|
||||
;LD B,28
|
||||
DSKMNT2:
|
||||
;LD A,(HL)
|
||||
;INC HL
|
||||
;CALL COUT
|
||||
;DJNZ DSKMNT2
|
||||
CALL CHUSB_PRTPREFIX ; PRINT DEVICE PREFIX
|
||||
LD HL,HB_WRKBUF + 8
|
||||
LD B,28
|
||||
CHUSB_DSKMNT2:
|
||||
LD A,(HL)
|
||||
INC HL
|
||||
CALL COUT
|
||||
DJNZ CHUSB_DSKMNT2
|
||||
#ENDIF
|
||||
;
|
||||
XOR A
|
||||
RET
|
||||
;
|
||||
; PERFORM DISK SIZE
|
||||
@@ -1081,17 +1159,30 @@ CHUSB_STR_ST_MAP:
|
||||
CHUSB_STR_STOK .TEXT "OK$"
|
||||
CHUSB_STR_STNOMEDIA .TEXT "NO MEDIA$"
|
||||
CHUSB_STR_STCMDERR .TEXT "COMMAND ERROR$"
|
||||
CHUSB_STR_STIOERR .TEXT "IO ERROR$"
|
||||
CHUSB_STR_STIOERR .TEXT "IO ERROR$"
|
||||
CHUSB_STR_STTO .TEXT "TIMEOUT$"
|
||||
CHUSB_STR_STNOTSUP .TEXT "NOT SUPPORTED$"
|
||||
CHUSB_STR_STUNK .TEXT "UNKNOWN ERROR$"
|
||||
|
||||
;
|
||||
;==================================================================================================
|
||||
; CH375/376 SD CARD SUB-DRIVER
|
||||
;==================================================================================================
|
||||
;
|
||||
; CH DEVICE CONFIGURATION
|
||||
#DEFINE CHSD_IMGFILE "DISK.IMG"
|
||||
;
|
||||
CHSD_FASTIO .EQU TRUE ; USE INIR/OTIR?
|
||||
;
|
||||
; CHUSB DEVICE STATUS
|
||||
;
|
||||
CHSD_STOK .EQU 0
|
||||
CHSD_STNOMEDIA .EQU -1
|
||||
CHSD_STCMDERR .EQU -2
|
||||
CHSD_STIOERR .EQU -3
|
||||
CHSD_STTO .EQU -4
|
||||
CHSD_STNOTSUP .EQU -5
|
||||
CHSD_STNOFILE .EQU -6
|
||||
;
|
||||
; CHSD DEVICE CONFIGURATION
|
||||
;
|
||||
CHSD_CFGSIZ .EQU 12 ; SIZE OF USB CFG TBL ENTRIES
|
||||
;
|
||||
@@ -1144,36 +1235,581 @@ CHSD_INIT:
|
||||
INC A ; BUMP TO NEXT UNIT NUM TO ASSIGN
|
||||
LD (CHSD_DEVNUM),A ; SAVE IT
|
||||
;
|
||||
CALL NEWLINE ; FORMATTING
|
||||
PRTS("CHSD$") ; LABEL FOR IO ADDRESS
|
||||
LD A,(IY+CH_DEV) ; GET DEVICE NUM
|
||||
CALL PRTDECB ; PRINT IT
|
||||
CALL PC_COLON ; FORMATTING
|
||||
; ADD UNIT TO GLOBAL DISK UNIT TABLE
|
||||
LD BC,CHSD_FNTBL ; BC := FUNC TABLE ADR
|
||||
PUSH IY ; CFG ENTRY POINTER
|
||||
POP DE ; COPY TO DE
|
||||
CALL DIO_ADDENT ; ADD ENTRY TO GLOBAL DISK DEV TABLE
|
||||
;
|
||||
CALL CHSD_RESET ; RESET & DISCOVER MEDIA
|
||||
#IF (CHSDTRACE <= 1)
|
||||
CALL NZ,CHSD_PRTSTAT
|
||||
#ENDIF
|
||||
RET NZ ; ABORT ON FAILURE
|
||||
;
|
||||
; START PRINTING DEVICE INFO
|
||||
CALL CHSD_PRTPREFIX ; PRINT DEVICE PREFIX
|
||||
;
|
||||
; PRINT STORAGE CAPACITY (BLOCK COUNT)
|
||||
PRTS(" BLOCKS=0x$") ; PRINT FIELD LABEL
|
||||
LD A,CHSD_MEDCAP ; OFFSET TO CAPACITY FIELD
|
||||
CALL LDHLIYA ; HL := IY + A, REG A TRASHED
|
||||
CALL LD32 ; GET THE CAPACITY VALUE
|
||||
CALL PRTHEX32 ; PRINT HEX VALUE
|
||||
;
|
||||
; PRINT STORAGE SIZE IN MB
|
||||
PRTS(" SIZE=$") ; PRINT FIELD LABEL
|
||||
LD B,11 ; 11 BIT SHIFT TO CONVERT BLOCKS --> MB
|
||||
CALL SRL32 ; RIGHT SHIFT
|
||||
CALL PRTDEC32 ; PRINT DWORD IN DECIMAL
|
||||
PRTS("MB$") ; PRINT SUFFIX
|
||||
;
|
||||
XOR A ; SIGNAL SUCCESS
|
||||
RET
|
||||
;
|
||||
; DRIVER FUNCTION TABLE
|
||||
;
|
||||
CHSD_FNTBL:
|
||||
.DW CHSD_STATUS
|
||||
.DW CHSD_RESET
|
||||
.DW CHSD_SEEK
|
||||
.DW CHSD_READ
|
||||
.DW CHSD_WRITE
|
||||
.DW CHSD_VERIFY
|
||||
.DW CHSD_FORMAT
|
||||
.DW CHSD_DEVICE
|
||||
.DW CHSD_MEDIA
|
||||
.DW CHSD_DEFMED
|
||||
.DW CHSD_CAP
|
||||
.DW CHSD_GEOM
|
||||
#IF (($ - CHSD_FNTBL) != (DIO_FNCNT * 2))
|
||||
.ECHO "*** INVALID CHSD FUNCTION TABLE ***\n"
|
||||
#ENDIF
|
||||
;
|
||||
CHSD_VERIFY:
|
||||
CHSD_FORMAT:
|
||||
CHSD_DEFMED:
|
||||
SYSCHKERR(ERR_NOTIMPL) ; NOT IMPLEMENTED
|
||||
RET
|
||||
;
|
||||
;
|
||||
;
|
||||
CHSD_READ:
|
||||
LD A,CH_MODE_SD ; REQUEST SD MODE
|
||||
CALL CH_SETMODE ; DO IT
|
||||
JP NZ,CHSD_CMDERR ; HANDLE ERROR
|
||||
;
|
||||
CALL HB_DSKREAD ; HOOK HBIOS DISK READ SUPERVISOR
|
||||
LD (CHSD_DSKBUF),HL ; SAVE DISK BUFFER ADDRESS
|
||||
CALL CHSD_RWSTART ; SET LBA OFFSET
|
||||
RET NZ
|
||||
;
|
||||
;PRTS("\n\rREAD:$") ; *DEBUG*
|
||||
LD A,CH_CMD_BYTERD ; BYTE READ
|
||||
CALL CH_CMD ; SEND COMMAND
|
||||
CALL CH_NAP
|
||||
LD A,0 ; LSB
|
||||
CALL CH_WR ; SEND IT
|
||||
LD A,2 ; MSB
|
||||
CALL CH_WR ; SEND IT
|
||||
CALL CH_POLL ; GET RESULT
|
||||
;CALL PC_SPACE ; *DEBUG*
|
||||
;CALL PRTHEXBYTE ; *DEBUG*
|
||||
CP $1D ; DATA READY TO READ?
|
||||
JP NZ,CHSD_IOERR ; HANDLE I/O ERROR
|
||||
;
|
||||
LD HL,(CHSD_DSKBUF)
|
||||
CHSD_READ1:
|
||||
CALL CH_CMD_RD ; SEND READ USB DATA CMD
|
||||
CALL CH_RD ; GET DATA LENGTH
|
||||
;CALL PC_SPACE ; *DEBUG*
|
||||
;CALL PRTHEXBYTE ; *DEBUG*
|
||||
;
|
||||
#IF (CHSD_FASTIO)
|
||||
LD B,A ; BYTE COUNT TO READ
|
||||
LD C,(IY+CH_IOBASE) ; BASE PORT
|
||||
INIR ; DO IT FAST
|
||||
#ELSE
|
||||
LD B,A ; SAVE IT
|
||||
CHSD_READ2:
|
||||
CALL CH_RD ; GET DATA BYTE
|
||||
LD (HL),A ; SAVE IN BUFFER
|
||||
INC HL ; INC BUF PTR
|
||||
DJNZ CHSD_READ2 ; LOOP TILL DONE W/ ALL BYTES
|
||||
#ENDIF
|
||||
;
|
||||
LD A,CH_CMD_BYTERDGO ; BYTE READ GO COMMAND
|
||||
CALL CH_CMD ; SEND IT
|
||||
CALL CH_NAP
|
||||
CALL CH_POLL ; GET RESULT
|
||||
;CALL PC_SPACE ; *DEBUG*
|
||||
;CALL PRTHEXBYTE ; *DEBUG*
|
||||
CP $1D ; MORE?
|
||||
JR Z,CHSD_READ1 ; IF SO, GET MORE
|
||||
CP $14 ; GOOD FINISH?
|
||||
JP NZ,CHSD_IOERR ; HANDLE ERROR
|
||||
;
|
||||
; INCREMENT LBA
|
||||
PUSH HL ; SAVE HL
|
||||
LD A,CHSD_LBA ; LBA OFFSET
|
||||
CALL LDHLIYA ; HL := IY + A, REG A TRASHED
|
||||
CALL INC32HL ; INCREMENT THE VALUE
|
||||
POP HL ; RESTORE HL
|
||||
;
|
||||
XOR A ; SIGNAL SUCCESS
|
||||
RET
|
||||
;
|
||||
;
|
||||
;
|
||||
CHSD_WRITE:
|
||||
LD A,CH_MODE_SD ; REQUEST SD MODE
|
||||
CALL CH_SETMODE ; DO IT
|
||||
JP NZ,CHSD_CMDERR ; HANDLE ERROR
|
||||
;
|
||||
CALL HB_DSKWRITE ; HOOK HBIOS DISK WRITE SUPERVISOR
|
||||
LD (CHSD_DSKBUF),HL ; SAVE DISK BUFFER ADDRESS
|
||||
CALL CHSD_RWSTART ; SET LBA OFFSET'
|
||||
RET NZ
|
||||
;
|
||||
;PRTS("\n\rWRITE:$") ; *DEBUG*
|
||||
LD A,CH_CMD_BYTEWR ; BYTE WRITE
|
||||
CALL CH_CMD ; SEND COMMAND
|
||||
LD A,0 ; LSB
|
||||
CALL CH_WR ; SEND IT
|
||||
LD A,2 ; MSB
|
||||
CALL CH_WR ; SEND IT
|
||||
CALL CH_POLL ; GET RESULT
|
||||
;CALL PC_SPACE ; *DEBUG*
|
||||
;CALL PRTHEXBYTE ; *DEBUG*
|
||||
CP $1E ; DATA READY TO GO?
|
||||
JP NZ,CHSD_IOERR ; HANDLE I/O ERROR
|
||||
;
|
||||
LD HL,(CHSD_DSKBUF)
|
||||
CHSD_WRITE1:
|
||||
LD A,CH_CMD_WRREQDAT ; WRITE REQUESTED DATA CMD
|
||||
CALL CH_CMD ; SEND IT
|
||||
CALL CH_RD ; GET DATA LENGTH
|
||||
;CALL PC_SPACE ; *DEBUG*
|
||||
;CALL PRTHEXBYTE ; *DEBUG*
|
||||
;
|
||||
#IF (CHSD_FASTIO)
|
||||
LD B,A ; BYTE COUNT TO WRITE
|
||||
LD C,(IY+CH_IOBASE) ; BASE PORT
|
||||
OTIR ; DO IT FAST
|
||||
#ELSE
|
||||
LD B,A ; SAVE IT
|
||||
CHSD_WRITE2:
|
||||
CALL CH_WR ; WRITE DATA BYTE
|
||||
LD (HL),A ; SAVE IN BUFFER
|
||||
INC HL ; INC BUF PTR
|
||||
DJNZ CHSD_WRITE2 ; LOOP TILL DONE W/ ALL BYTES
|
||||
#ENDIF
|
||||
;
|
||||
LD A,CH_CMD_BYTEWRGO ; BYTE WRITE GO COMMAND
|
||||
CALL CH_CMD ; SEND IT
|
||||
CALL CH_NAP
|
||||
CALL CH_POLL ; GET RESULT
|
||||
;CALL PC_SPACE ; *DEBUG*
|
||||
;CALL PRTHEXBYTE ; *DEBUG*
|
||||
CP $1E ; MORE?
|
||||
JR Z,CHSD_WRITE1 ; IF SO, SEND MORE
|
||||
CP $14 ; GOOD FINISH?
|
||||
JP NZ,CHSD_IOERR ; HANDLE ERROR
|
||||
;
|
||||
; INCREMENT LBA
|
||||
PUSH HL ; SAVE HL
|
||||
LD A,CHSD_LBA ; LBA OFFSET
|
||||
CALL LDHLIYA ; HL := IY + A, REG A TRASHED
|
||||
CALL INC32HL ; INCREMENT THE VALUE
|
||||
POP HL ; RESTORE HL
|
||||
;
|
||||
XOR A ; SIGNAL SUCCESS
|
||||
RET
|
||||
;
|
||||
; SEEK TO CURRENT LBA
|
||||
;
|
||||
CHSD_RWSTART:
|
||||
;PRTS("\n\rRWST:$") ; *DEBUG*
|
||||
LD A,CH_CMD_BYTE_LOC ; BYTE LOCATE COMMAND (SEEK)
|
||||
CALL CH_CMD ; SEND IT
|
||||
;
|
||||
; GET CURRENT LBA OFFSET
|
||||
LD A,CHSD_LBA ; OFFSET TO CAPACITY FIELD
|
||||
CALL LDHLIYA ; HL := IY + A, REG A TRASHED
|
||||
CALL LD32 ; OFFSET = DE:HL
|
||||
;
|
||||
; CONVERT OFFSET FROM LBA TO BYTE
|
||||
LD B,9
|
||||
CHSD_RWSTART1:
|
||||
SLA L
|
||||
RL H
|
||||
RL E
|
||||
RL D
|
||||
DJNZ CHSD_RWSTART1
|
||||
;CALL PRTHEX32 ; *DEBUG*
|
||||
;
|
||||
; SEND THE BYTE OFFSET (LSB FIRST)
|
||||
LD A,L
|
||||
CALL CH_WR
|
||||
LD A,H
|
||||
CALL CH_WR
|
||||
LD A,E
|
||||
CALL CH_WR
|
||||
LD A,D
|
||||
CALL CH_WR
|
||||
;
|
||||
CALL CH_POLL ; WAIT FOR RESPONSE
|
||||
;CALL PC_SPACE ; *DEBUG*
|
||||
;CALL PRTHEXBYTE ; *DEBUG*
|
||||
CP $14 ; CHECK RESULT
|
||||
JP NZ,CHUSB_CMDERR ; HANDLE CMD ERROR
|
||||
;
|
||||
XOR A
|
||||
RET
|
||||
;
|
||||
;
|
||||
;
|
||||
CHSD_STATUS:
|
||||
; RETURN UNIT STATUS
|
||||
LD A,(IY+CHSD_STAT) ; GET STATUS OF SELECTED DEVICE
|
||||
OR A ; SET FLAGS
|
||||
RET ; AND RETURN
|
||||
;
|
||||
; RESET THE INTERFACE AND REDISCOVER MEDIA
|
||||
;
|
||||
CHSD_RESET:
|
||||
;PRTS("\n\rRES SD:$") ; *DEBUG*
|
||||
;
|
||||
; ACTIVATE SD MODE
|
||||
LD A,CH_CMD_MODE ; SET MODE COMMAND
|
||||
CALL CH_CMD ; SEND IT
|
||||
LD A,3 ; SD MODE
|
||||
CALL CH_WR ; SEND IT
|
||||
CALL CH_NAP ; SMALL WAIT
|
||||
CALL CH_RD ; GET RESULT
|
||||
;CALL PC_SPACE ; *DEBUG*
|
||||
;CALL PRTHEXBYTE ; *DEBUG*
|
||||
CALL CH_NAP ; SMALL WAIT
|
||||
;
|
||||
LD A,CH_MODE_SD ; WE ARE NOW IN SD MODE
|
||||
LD (CH_MODE),A ; SAVE IT
|
||||
;
|
||||
CALL CHSD_DSKMNT ; MOUNT DISK
|
||||
RET NZ
|
||||
;
|
||||
; OPEN DISK IMAGE FILE
|
||||
LD DE,CHSD_FNAME
|
||||
CALL CHSD_FOPEN
|
||||
RET NZ
|
||||
;
|
||||
; GET FILESIZE
|
||||
CALL CHSD_FILESIZE
|
||||
RET NZ
|
||||
;
|
||||
; SET STATUS AND RETURN
|
||||
XOR A ; CLEAR STATUS
|
||||
LD (IY+CHSD_STAT),A ; RECORD STATUS
|
||||
OR A ; SET FLAGS
|
||||
RET ; AND RETURN
|
||||
;
|
||||
;
|
||||
;
|
||||
CHSD_DEVICE:
|
||||
LD D,DIODEV_CHSD ; D := DEVICE TYPE
|
||||
LD E,(IY+CH_DEV) ; E := PHYSICAL DEVICE NUMBER
|
||||
LD C,%00110010 ; SD HARD DISK ATTRIBUTES
|
||||
LD H,(IY+CH_TYPE) ; H := MODE
|
||||
LD L,(IY+CH_IOBASE) ; L := BASE I/O ADDRESS
|
||||
XOR A ; SIGNAL SUCCESS
|
||||
RET
|
||||
;
|
||||
; CHSD_GETMED
|
||||
;
|
||||
CHSD_MEDIA:
|
||||
LD A,E ; GET FLAGS
|
||||
OR A ; SET FLAGS
|
||||
JR Z,CHSD_MEDIA1 ; JUST REPORT CURRENT STATUS AND MEDIA
|
||||
CALL CHSD_RESET ; RESET CHSD INTERFACE
|
||||
;
|
||||
CHSD_MEDIA1:
|
||||
LD A,(IY+CHSD_STAT) ; GET STATUS
|
||||
OR A ; SET FLAGS
|
||||
LD D,0 ; NO MEDIA CHANGE DETECTED
|
||||
LD E,MID_HD ; ASSUME WE ARE OK
|
||||
RET Z ; RETURN IF GOOD INIT
|
||||
LD E,MID_NONE ; SIGNAL NO MEDIA
|
||||
LD A,ERR_NOMEDIA ; NO MEDIA ERROR
|
||||
OR A ; SET FLAGS
|
||||
RET ; AND RETURN
|
||||
;
|
||||
;
|
||||
;
|
||||
CHSD_SEEK:
|
||||
BIT 7,D ; CHECK FOR LBA FLAG
|
||||
CALL Z,HB_CHS2LBA ; CLEAR MEANS CHS, CONVERT TO LBA
|
||||
RES 7,D ; CLEAR FLAG REGARDLESS (DOES NO HARM IF ALREADY LBA)
|
||||
LD (IY+CHSD_LBA+0),L ; SAVE NEW LBA
|
||||
LD (IY+CHSD_LBA+1),H ; ...
|
||||
LD (IY+CHSD_LBA+2),E ; ...
|
||||
LD (IY+CHSD_LBA+3),D ; ...
|
||||
XOR A ; SIGNAL SUCCESS
|
||||
RET ; AND RETURN
|
||||
;
|
||||
;
|
||||
;
|
||||
CHSD_CAP:
|
||||
LD A,(IY+CHSD_STAT) ; GET STATUS
|
||||
PUSH AF ; SAVE IT
|
||||
LD A,CHSD_MEDCAP ; OFFSET TO CAPACITY FIELD
|
||||
CALL LDHLIYA ; HL := IY + A, REG A TRASHED
|
||||
CALL LD32 ; GET THE CURRENT CAPACITY INTO DE:HL
|
||||
LD BC,512 ; 512 BYTES PER BLOCK
|
||||
POP AF ; RECOVER STATUS
|
||||
OR A ; SET FLAGS
|
||||
RET
|
||||
;
|
||||
;
|
||||
;
|
||||
CHSD_GEOM:
|
||||
; FOR LBA, WE SIMULATE CHS ACCESS USING 16 HEADS AND 16 SECTORS
|
||||
; RETURN HS:CC -> DE:HL, SET HIGH BIT OF D TO INDICATE LBA CAPABLE
|
||||
CALL CHSD_CAP ; GET TOTAL BLOCKS IN DE:HL, BLOCK SIZE TO BC
|
||||
LD L,H ; DIVIDE BY 256 FOR # TRACKS
|
||||
LD H,E ; ... HIGH BYTE DISCARDED, RESULT IN HL
|
||||
LD D,16 | $80 ; HEADS / CYL = 16, SET LBA CAPABILITY BIT
|
||||
LD E,16 ; SECTORS / TRACK = 16
|
||||
RET ; DONE, A STILL HAS CHSD_CAP STATUS
|
||||
;
|
||||
; CH37X HELPER ROUTINES
|
||||
;
|
||||
;
|
||||
; PERFORM DISK MOUNT
|
||||
;
|
||||
CHSD_DSKMNT:
|
||||
;PRTS("\n\rMOUNT:$") ; *DEBUG*
|
||||
LD A,CH_CMD_DSKMNT ; DISK QUERY
|
||||
CALL CH_CMD ; DO IT
|
||||
CALL CH_POLL ; WAIT FOR RESPONSE
|
||||
;CALL PC_SPACE ; *DEBUG*
|
||||
;CALL PRTHEXBYTE ; *DEBUG*
|
||||
CP $82 ; NO DISK?
|
||||
JP Z,CHSD_NOMEDIA ; HANDLE NO MEDIA ERROR
|
||||
CP $14 ; SUCCESS?
|
||||
JP NZ,CHSD_CMDERR ; HANDLE ERROR
|
||||
;
|
||||
#IF FALSE
|
||||
CALL CH_CMD_RD ; SEND READ COMMAND
|
||||
CALL CH_RD ; GET LENGTH
|
||||
;CALL PC_SPACE ; *DEBUG*
|
||||
;CALL PRTHEXBYTE ; *DEBUG*
|
||||
LD B,A ; LOOP COUNTER
|
||||
LD HL,HB_WRKBUF ; USE WORK BUFFER FOR DATA
|
||||
CHSD_DSKMNT1:
|
||||
CALL CH_RD ; GET A BYTE
|
||||
LD (HL),A ; SAVE IT
|
||||
INC HL ; BUMP BUF PTR
|
||||
DJNZ CHSD_DSKMNT1 ; LOOP FOR ALL DATA
|
||||
;
|
||||
;LD DE,HB_WRKBUF ; *DEBUG*
|
||||
;CALL DUMP_BUFFER ; *DEBUG*
|
||||
;
|
||||
CALL CHSD_PRTPREFIX ; PRINT DEVICE PREFIX
|
||||
LD HL,HB_WRKBUF + 8
|
||||
LD B,28
|
||||
CHSD_DSKMNT2:
|
||||
LD A,(HL)
|
||||
INC HL
|
||||
CALL COUT
|
||||
DJNZ CHSD_DSKMNT2
|
||||
#ENDIF
|
||||
;
|
||||
XOR A
|
||||
RET
|
||||
;
|
||||
; SET FILE NAME
|
||||
;
|
||||
CHSD_SETFNAME:
|
||||
;PRTS("\n\rSETFNAME:$") ; *DEBUG*
|
||||
LD A,CH_CMD_SET_FN ; SET FILE NAME COMMAND
|
||||
CALL CH_CMD ; SEND IT
|
||||
CALL CH_NAP
|
||||
;CALL DELAY ; MAY NOT BE NEEDED
|
||||
;CALL PC_SPACE ; *DEBUG*
|
||||
CHSD_SETFNAME1:
|
||||
;CALL DELAY
|
||||
LD A,(DE) ; GET NEXT BYTE
|
||||
INC DE ; BUMP POINTER
|
||||
CALL CH_WR ; SEND IT
|
||||
;CALL COUT ; *DEBUG*
|
||||
OR A ; CHECK FOR NUL (EOS)
|
||||
RET Z ; IF NUL, DONE
|
||||
JR CHSD_SETFNAME1 ; SEND MORE CHARACTERS
|
||||
;
|
||||
; OPEN FILE
|
||||
;
|
||||
CHSD_FOPEN:
|
||||
CALL CHSD_SETFNAME
|
||||
;PRTS("\n\rFOPEN:$") ; *DEBUG*
|
||||
LD A,CH_CMD_FOPEN ; FILE OPEN COMMAND
|
||||
CALL CH_CMD ; SEND IT
|
||||
CALL CH_POLL ; WAIT FOR RESULT
|
||||
;CALL PC_SPACE ; *DEBUG*
|
||||
;CALL PRTHEXBYTE ; *DEBUG*
|
||||
CP $42 ; MISSING FILE?
|
||||
JP Z,CHSD_NOFILE ; HANDLE ERROR
|
||||
CP $14 ; SUCCESS?
|
||||
JP NZ,CHSD_IOERR ; HANDLE ERROR
|
||||
RET ; RETURN WITH ZF SET APPROPRIATELY
|
||||
;
|
||||
; GET FILE SIZE
|
||||
;
|
||||
CHSD_FILESIZE:
|
||||
;PRTS("\n\rFSIZE:$")
|
||||
LD A,CH_CMD_FILESIZE ; FILE SIZE COMMAND
|
||||
CALL CH_CMD ; SEND IT
|
||||
LD A,$68 ; REQUIRED CMD PARAMETER
|
||||
CALL CH_WR ; SEND IT
|
||||
CALL CH_NAP
|
||||
LD A,CHSD_MEDCAP ; MEDIA CAPACITY OFFSET
|
||||
CALL LDHLIYA ; HL := IY + A, REG A TRASHED
|
||||
PUSH HL ; SAVE ADDRESS
|
||||
CALL CH_RD
|
||||
LD L,A
|
||||
CALL CH_RD
|
||||
LD H,A
|
||||
CALL CH_RD
|
||||
LD E,A
|
||||
CALL CH_RD
|
||||
LD D,A
|
||||
;CALL PC_SPACE ; *DEBUG*
|
||||
;CALL PRTHEX32 ; *DEBUG*
|
||||
LD B,9 ; ROTATE 9 BITS FOR DIV 512
|
||||
CHSD_FILESIZE1:
|
||||
SRL D
|
||||
RR E
|
||||
RR H
|
||||
RR L
|
||||
DJNZ CHSD_FILESIZE1 ; LOOP TILL DONE
|
||||
POP BC ; RECOVER ADDRESS TO BC
|
||||
;CALL PC_SPACE ; *DEBUG*
|
||||
;CALL PRTHEX32 ; *DEBUG*
|
||||
CALL ST32 ; STORE IT
|
||||
XOR A ; SIGNAL SUCCESS
|
||||
RET ; AND DONE
|
||||
;
|
||||
; ERROR HANDLERS
|
||||
;
|
||||
;
|
||||
CHSD_NOFILE:
|
||||
LD A,CHSD_STNOFILE
|
||||
JR CHSD_ERR
|
||||
;
|
||||
CHSD_NOMEDIA:
|
||||
LD A,CHSD_STNOMEDIA
|
||||
JR CHSD_ERR
|
||||
;
|
||||
CHSD_CMDERR:
|
||||
LD A,CHSD_STCMDERR
|
||||
JR CHSD_ERR
|
||||
;
|
||||
CHSD_IOERR:
|
||||
LD A,CHSD_STIOERR
|
||||
JR CHSD_ERR
|
||||
;
|
||||
CHSD_TO:
|
||||
LD A,CHSD_STTO
|
||||
JR CHSD_ERR
|
||||
;
|
||||
CHSD_NOTSUP:
|
||||
LD A,CHSD_STNOTSUP
|
||||
JR CHSD_ERR
|
||||
;
|
||||
CHSD_ERR:
|
||||
LD (IY+CHSD_STAT),A ; SAVE NEW STATUS
|
||||
;
|
||||
CHSD_ERR2:
|
||||
#IF (CHSDTRACE >= 2)
|
||||
CALL CHSD_PRTSTAT
|
||||
#ENDIF
|
||||
OR A ; SET FLAGS
|
||||
RET
|
||||
;
|
||||
;
|
||||
;
|
||||
CHSD_PRTERR:
|
||||
RET Z ; DONE IF NO ERRORS
|
||||
; FALL THRU TO CHSD_PRTSTAT
|
||||
;
|
||||
; PRINT FULL DEVICE STATUS LINE
|
||||
;
|
||||
CHSD_PRTSTAT:
|
||||
PUSH AF
|
||||
PUSH DE
|
||||
PUSH HL
|
||||
LD A,(IY+CHSD_STAT)
|
||||
CALL CHSD_PRTPREFIX ; PRINT UNIT PREFIX
|
||||
CALL PC_SPACE ; FORMATTING
|
||||
CALL CHSD_PRTSTATSTR
|
||||
POP HL
|
||||
POP DE
|
||||
POP AF
|
||||
RET
|
||||
;
|
||||
; PRINT STATUS STRING
|
||||
;
|
||||
CHSD_PRTSTATSTR:
|
||||
PUSH AF
|
||||
PUSH DE
|
||||
PUSH HL
|
||||
LD A,(IY+CHSD_STAT)
|
||||
NEG
|
||||
LD HL,CHSD_STR_ST_MAP
|
||||
ADD A,A
|
||||
CALL ADDHLA
|
||||
LD E,(HL)
|
||||
INC HL
|
||||
LD D,(HL)
|
||||
CALL WRITESTR
|
||||
POP HL
|
||||
POP DE
|
||||
POP AF
|
||||
RET
|
||||
;
|
||||
; PRINT DIAGNONSTIC PREFIX
|
||||
;
|
||||
CHSD_PRTPREFIX:
|
||||
PUSH AF
|
||||
CALL NEWLINE
|
||||
PRTS("CHSD$")
|
||||
LD A,(IY+CH_DEV) ; GET CURRENT DEVICE NUM
|
||||
CALL PRTDECB
|
||||
CALL PC_COLON
|
||||
POP AF
|
||||
RET
|
||||
|
||||
|
||||
CHSD_DEVNUM .DB 0 ; TEMP DEVICE NUM USED DURING INIT
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
;
|
||||
;=============================================================================
|
||||
; DATA STORAGE
|
||||
;=============================================================================
|
||||
;
|
||||
CH_FWVER .DW 0,0 ; MMNNBBB (M=MAJOR, N=MINOR, B=BUILD)
|
||||
CHSD_DEVNUM .DB 0 ; TEMP DEVICE NUM USED DURING INIT
|
||||
CHSD_DSKBUF .DW 0
|
||||
;
|
||||
CHSD_IOFNADR .DW 0 ; PENDING IO FUNCTION ADDRESS
|
||||
CHSD_FNAME .DB "/", CHSD_IMGFILE, 0
|
||||
;
|
||||
CHSD_DSKBUF .DW 0
|
||||
CHSD_STR_ST_MAP:
|
||||
.DW CHSD_STR_STOK
|
||||
.DW CHSD_STR_STNOMEDIA
|
||||
.DW CHSD_STR_STCMDERR
|
||||
.DW CHSD_STR_STIOERR
|
||||
.DW CHSD_STR_STTO
|
||||
.DW CHSD_STR_STNOTSUP
|
||||
.DW CHSD_STR_STNOFILE
|
||||
;
|
||||
CHSD_DSKSTAT .DB 0
|
||||
CHSD_ERRCODE .DW 0,0
|
||||
CHSD_CSDBUF .FILL 16,0
|
||||
;
|
||||
CHSD_CMD .DB 0
|
||||
;
|
||||
CHSD_TIMEOUT .DW $0000 ; FIX: MAKE THIS CPU SPEED RELATIVE
|
||||
CHSD_STR_STOK .TEXT "OK$"
|
||||
CHSD_STR_STNOMEDIA .TEXT "NO MEDIA$"
|
||||
CHSD_STR_STCMDERR .TEXT "COMMAND ERROR$"
|
||||
CHSD_STR_STIOERR .TEXT "IO ERROR$"
|
||||
CHSD_STR_STTO .TEXT "TIMEOUT$"
|
||||
CHSD_STR_STNOTSUP .TEXT "NOT SUPPORTED$"
|
||||
CHSD_STR_STNOFILE .TEXT "MISSING "
|
||||
.TEXT CHSD_IMGFILE
|
||||
.TEXT " FILE$"
|
||||
CHSD_STR_STUNK .TEXT "UNKNOWN ERROR$"
|
||||
|
||||
@@ -71,6 +71,8 @@
|
||||
;
|
||||
#DEFINE HBIOS
|
||||
;
|
||||
SUPCTS .EQU FALSE ; SUPPRESS CTS DURING HBIOS BOOT
|
||||
;
|
||||
; MAKE SURE EXACTLY ONE OF ROMBOOT, APPBOOT, IMGBOOT IS DEFINED.
|
||||
;
|
||||
MODCNT .EQU 0
|
||||
@@ -991,7 +993,8 @@ HBX_BUF_END .EQU $
|
||||
.DW 0 ; HB_DSTADR: BNKCPY DESTINATION ADDRESS
|
||||
.DB BID_USR ; HB_DSTBNK: BNKCPY DESTINATION BANK ID
|
||||
.DW 0 ; HB_CPYLEN: BNKCPY LENGTH
|
||||
.FILL 4,0 ; FILLER, RESERVED FOR FUTURE HBIOS USE
|
||||
.DW 0 ; RESERVED FOR OPTIONAL TICK CTR, PLATFORM DEPENDENT
|
||||
.DW 0 ; RESERVED FOR FUTURE HBIOS USE
|
||||
.DB 0 ; SHADOW VALUE FOR RTC LATCH PORT
|
||||
.DB $FE ; HB_LOCK: HBIOS MUTEX LOCK
|
||||
JP HBX_INVOKE ; HB_INVOKE: FIXED ADR ENTRY FOR HBX_INVOKE (ALT FOR RST 08)
|
||||
@@ -1114,12 +1117,17 @@ BOOTWAIT:
|
||||
JR NZ,BOOTWAIT
|
||||
#ENDIF
|
||||
;
|
||||
;#IF ((PLATFORM == PLT_MBC) | (PLATFORM == PLT_SBC))
|
||||
; INITIALIZE RTC LATCH BYTE
|
||||
; EARLY RTC LATCH BYTE INITIALIZATION
|
||||
; FOR SOME PLATFORMS THIS CONTROLS HI/LO SPEED CIRCUIT
|
||||
LD A,(RTCDEFVAL) ; GET DEFAULT VALUE
|
||||
; NOTE: WE WANT TO USE (RTCDEFVAL) HERE, BUT THE Z2 MEMORY
|
||||
; MANAGER STARTS UP WITH THE FIRST 16K OF ROM MAPPED TO ALL
|
||||
; 4 16K BANKS OF CPU SPACE. SO, IF RTCDEVFAL IS LOCATED AFTER
|
||||
; PAST 16K, WE DON'T HAVE ACCESS TO IT. FOR NOW, WE JUST USE
|
||||
; RTCDEF WHICH IS SUBOPTIMAL, BUT PROBABLY DOES NOT CAUSE ANY
|
||||
; PROBLEMS.
|
||||
;LD A,(RTCDEFVAL) ; GET DEFAULT VALUE
|
||||
LD A,RTCDEF ; DEFAULT VALUE
|
||||
OUT (RTCIO),A ; SET IT
|
||||
;#ENDIF
|
||||
;
|
||||
#IF (PLATFORM == PLT_N8)
|
||||
LD A,N8_DEFACR ; ENSURE N8 ACR
|
||||
@@ -1141,7 +1149,9 @@ BOOTWAIT:
|
||||
XOR A ; LED IS INVERTED, TURN IT ON
|
||||
#ENDIF
|
||||
#IF (LEDMODE == LEDMODE_RTC)
|
||||
LD A,(RTCDEFVAL) ; DEFAULT LATCH VALUE
|
||||
; CAN'T USE (RTCDEFVAL) YET, SEE COMMENTS ABOVE
|
||||
;LD A,(RTCDEFVAL) ; DEFAULT LATCH VALUE
|
||||
LD A,RTCDEF ; DEFAULT LATCH VALUE
|
||||
OR %00000001 ; LED 0 ON
|
||||
#ENDIF
|
||||
OUT (LEDPORT),A
|
||||
@@ -1432,11 +1442,15 @@ S100MON_SKIP:
|
||||
LD A,(HB_CURBNK) ; GET HB_CURBNK
|
||||
LD (HBX_LOC - 2),A ; ... AND SAVE TEMP FOR APPBNK
|
||||
;
|
||||
; THE RTCVAL FIELD OF THE PROXY DATA NEEDS TO BE INITIALIZED HERE
|
||||
; BECAUSE IT CANNOT BE PRE-INITIALIZED (SEE COMMENTS ABOVE WHERE
|
||||
; RTCVAL EQUATE IS DEFINED).
|
||||
; WE CAN NOW DO THE REAL INITIALIZATION OF THE RTC LATCH BASED ON
|
||||
; (RTCDEFVAL). AT THIS POINT WE SHOULD HAVE ACCESS TO THE ROM LOCATION
|
||||
; WHERE RTCDEFVAL IS STORED AND THE PROXY IS INSTALLED IN UPPER RAM
|
||||
; WHERE WE WILL STORE THE WORKING SHADOW COPY (HB_RTCVAL).
|
||||
; SEE COMMENTS ABOVE REGARDING THE FUNKY WAY THAT THE RTCDEFVAL IS
|
||||
; CREATED.
|
||||
;
|
||||
LD A,(RTCDEFVAL)
|
||||
OUT (RTCIO),A ; SET IT
|
||||
LD (HB_RTCVAL),A
|
||||
;
|
||||
#IFDEF TESTING
|
||||
@@ -1599,51 +1613,43 @@ MBC_SINGLE:
|
||||
;
|
||||
#ENDIF
|
||||
;
|
||||
; IF ALREADY EXECUTING IN RAM, BYPASS RAM BANK INSTALLATION
|
||||
;
|
||||
LD A,(HB_RAMFLAG)
|
||||
OR A
|
||||
JR NZ,HB_START1
|
||||
;
|
||||
; IF BID_BOOT AND BID_BIOS ARE THE SAME, THEN IT IS NEVER APPROPRIATE
|
||||
; TO COPY THE HBIOS IMAGE FROM BID_BOOT TO BID_BIOS. THIS IS TYPICALLY
|
||||
; THE CASE FOR A ROMLESS SYSTEM.
|
||||
;
|
||||
#IF (BID_BOOT != BID_BIOS)
|
||||
;
|
||||
; INSTALL HBIOS IN RAM BANK
|
||||
;
|
||||
LD A,(HB_CURBNK)
|
||||
;
|
||||
; CHECK TO SEE IF WE ARE ALREADY RUNNING IN THE HBIOS
|
||||
; BANK AND SKIP THE COPY IF SO (DON'T COPY OVER OURSELVES).
|
||||
; THIS SITUATION OCCURS ON A ROMLESS STARTUP OR WHEN DOING A
|
||||
; FULL RESTART OF A SYSTEM USING THE EXISTING HBIOS COPY.
|
||||
CP BID_BIOS
|
||||
JR Z,HB_START1
|
||||
;
|
||||
LD (HB_SRCBNK),A
|
||||
LD A,BID_BIOS
|
||||
LD (HB_DSTBNK),A
|
||||
LD HL,0
|
||||
LD DE,0
|
||||
LD BC,$8000
|
||||
#IF (MEMMGR == MM_Z280)
|
||||
#IF (MEMMGR == MM_Z280)
|
||||
CALL Z280_BNKCPY
|
||||
#ELSE
|
||||
#ELSE
|
||||
CALL HBX_BNKCPY
|
||||
#ENDIF
|
||||
#ENDIF
|
||||
;
|
||||
; TRANSITION TO HBIOS IN RAM BANK
|
||||
;
|
||||
#IF (MEMMGR == MM_Z280)
|
||||
#IF (MEMMGR == MM_Z280)
|
||||
LD A,BID_BIOS
|
||||
LD B,$10 ; FIRST SYSTEM PDR
|
||||
CALL Z280_BNKSEL
|
||||
JR HB_START1
|
||||
#ELSE
|
||||
#ELSE
|
||||
LD A,BID_BIOS ; BIOS BANK ID
|
||||
LD IX,HB_START1 ; EXECUTION RESUMES HERE
|
||||
CALL HBX_BNKCALL ; CONTINUE IN RAM BANK, DO NOT RETURN
|
||||
HALT ; WE SHOULD NOT COME BACK HERE!
|
||||
#ENDIF
|
||||
;
|
||||
#ENDIF
|
||||
;
|
||||
HB_RAMFLAG .DB FALSE ; INITIALLY FALSE, SET TO TRUE BELOW AFTER RAM TRANSITION
|
||||
;
|
||||
; EXECUTION RESUMES HERE AFTER SWITCH TO RAM BANK
|
||||
;
|
||||
HB_START1: ; BNKCALL ARRIVES HERE, BUT NOW RUNNING IN RAM BANK
|
||||
@@ -1857,11 +1863,13 @@ HB_CPU1:
|
||||
;
|
||||
; CLEAR DISPATCH TABLE ENTRIES
|
||||
;
|
||||
XOR A ; ZERO
|
||||
LD (CIO_CNT),A ; CIO DEVICES
|
||||
LD (DIO_CNT),A ; DIO DEVICES
|
||||
LD (VDA_CNT),A ; VDA DEVICES
|
||||
LD (SND_CNT),A ; SND DEVICES
|
||||
XOR A ; ZERO
|
||||
LD (CIO_CNT),A ; CIO DEVICES
|
||||
LD (DIO_CNT),A ; DIO DEVICES
|
||||
LD (VDA_CNT),A ; VDA DEVICES
|
||||
LD (SND_CNT),A ; SND DEVICES
|
||||
LD (RTC_DISPACT),A ; RTC DEVICE
|
||||
LD (DSKY_DISPACT),A ; DSKY DEVICE
|
||||
;
|
||||
#IF (DSRTCENABLE)
|
||||
CALL DSRTC_PREINIT
|
||||
@@ -2060,7 +2068,7 @@ HB_CPU3:
|
||||
LD A,(CB_CPUMHZ) ; CPU SPEED TO ACCUM AND INIT
|
||||
CALL DELAY_INIT ; .. SPEED COMPENSATED DELAY
|
||||
;
|
||||
#IF (INTMODE == 2)
|
||||
#IF ((INTMODE == 2) | ((INTMODE == 1) & (CPUFAM == CPU_Z180)))
|
||||
; SETUP Z80 IVT AND INT MODE 2
|
||||
LD A,HBX_IVT >> 8 ; SETUP HI BYTE OF IVT ADDRESS
|
||||
LD I,A ; ... AND PLACE IT IN I REGISTER
|
||||
@@ -2071,7 +2079,9 @@ HB_CPU3:
|
||||
OUT0 (Z180_IL),A ; ... AND PLACE IN Z180 IL REGISTER
|
||||
#ENDIF
|
||||
|
||||
#IF (INTMODE == 2)
|
||||
IM 2 ; SWITCH TO INT MODE 2
|
||||
#ENDIF
|
||||
#ENDIF
|
||||
;
|
||||
#IF (INTMODE == 3)
|
||||
@@ -2300,8 +2310,36 @@ HB_BOOTDLY:
|
||||
JR C,HB_CONRDY ; IF TOO HIGH, JUST USE FAILSAFE
|
||||
LD A,BOOTCON ; GET REQUESTED CONSOLE DEV
|
||||
LD (CB_CONDEV),A ; SAVE IT
|
||||
;
|
||||
HB_CONRDY:
|
||||
;
|
||||
#IF (SUPCTS)
|
||||
;
|
||||
; MOST SERIAL PORTS ARE CONFIGURED WITH HARDWARE FLOW CONTROL ENABLED.
|
||||
; IF THERE IS A PROBLEM WITH THE CTS SIGNAL, THEN OUTPUT TO THE CONSOLE
|
||||
; WILL BE STALLED WHICH CAN LEAD A USER TO THINK THE SYSTEM IS TOTALLY
|
||||
; DEAD WHEN, IN FACT, IT IS JUST WAITING FOR CTS TO BE ASSERTED. ALSO,
|
||||
; IF THE USER IS BOOTING TO A CRT DEVICE AND DISCONNECTS THE CONSOLE
|
||||
; SERIAL PORT, THE SYSTEM WILL WAIT FOR RTS AND NEVER BOOT. SO, HERE
|
||||
; WE SAVE THE ACTIVE CONSOLE CONFIGURATION, THEN TURN OFF HARDWARE
|
||||
; FLOW CONTROL. THE ORIGINAL CONFIGURATION WILL BE RESTORED BELOW
|
||||
; PRIOR TO LAUNCING THE ROM LOADER.
|
||||
;
|
||||
; RETRIEVE THE CONFIG FROM THE CONSOLE PORT
|
||||
LD B,BF_CIOQUERY ; HBIOS QUERY CIO CONFIG
|
||||
LD A,(CB_CONDEV) ; GET CONSOLE DEVICE
|
||||
LD (HB_BOOTCONSAV),A ; SAVE IT FOR LATER
|
||||
LD C,A ; BOOT CONSOLE TO C
|
||||
CALL HB_DISPATCH ; INTERNAL HBIOS CALL
|
||||
LD (HB_CONCFGSAV),DE ; SAVE CONFIG
|
||||
RES 5,D ; CLEAR RTS BIT
|
||||
LD B,BF_CIOINIT ; HBIOS CIO INIT
|
||||
LD A,(CB_CONDEV) ; GET CONSOLE DEVICE
|
||||
LD C,A ; BOOT CONSOLE TO C
|
||||
CALL HB_DISPATCH ; INTERNAL HBIOS CALL
|
||||
;
|
||||
#ENDIF
|
||||
;
|
||||
#IF (WBWDEBUG == USEMIO) ; OUTPUT ANY CACHED DEBUG TEXT
|
||||
LD HL,MIOOUTPTR
|
||||
LD E,(HL)
|
||||
@@ -2825,19 +2863,27 @@ HB_FP1:
|
||||
;
|
||||
HB_FP2:
|
||||
; IF SEC SWITCH IS SET, WE WANT TO BUMP TO SECONDARY
|
||||
; CRT OR SERIAL DEVICE. FOR NOW, WE ARE GOING TO CHEAT AND
|
||||
; JUST INCREMENT THE CONSOLE DEVICE UNIT. THIS SHOULD WORK
|
||||
; ASSUMING NORMAL ORDERING OF THE CHARACTER DEVICE UNITS.
|
||||
; CRT OR SERIAL DEVICE. IF AN OVERRIDE IS SPECIFIED USING
|
||||
; SECCON, USE THAT, OTHERWISE INCREMENT THE DEFAULT UNIT.
|
||||
; THIS SHOULD WORK ASSUMING NORMAL ORDERING OF THE
|
||||
; CHARACTER DEVICE UNITS.
|
||||
LD A,B ; RECOVER SWITCH SETTINGS
|
||||
AND SW_SEC ; TEST SEC BIT
|
||||
JR Z,HB_FPZ ; IF NOT SET, THEN ALL DONE
|
||||
;
|
||||
; INCREMENT CONSOLE UNIT, BUT MAKE SURE IT DOES NOT EXCEED
|
||||
; THE HIGHEST CHAR UNIT IN SYSTEM.
|
||||
LD A,(CIO_CNT) ; GET CHAR UNIT COUNT
|
||||
LD B,A ; MOVE TO B
|
||||
LD A,SECCON ; GET SEC CONSOLE SETTING
|
||||
CP $FF ; $FF MEANS USE INCREMENT
|
||||
JR NZ,HB_FP3 ; BYPASS IF NOT $FF
|
||||
;
|
||||
; INCREMENT CONSOLE UNIT
|
||||
LD A,(HB_NEWCON) ; GET NEW CONSOLE UNIT
|
||||
INC A ; BUMP TO SECONDARY
|
||||
;
|
||||
HB_FP3:
|
||||
; MAKE SURE NEW CONSOLE UNIT DOES NOT EXCEED THE HIGHEST
|
||||
; CHAR UNIT IN SYSTEM.
|
||||
CP B ; A (UNIT) >= B (CNT)?
|
||||
JR NC,HB_FPZ ; ABORT IF UNIT TOO HIGH
|
||||
LD (HB_NEWCON),A ; UPDATE NEW CONSOLE UNIT
|
||||
@@ -2848,6 +2894,19 @@ HB_FPZ:
|
||||
;
|
||||
INITSYS3:
|
||||
;
|
||||
#IF (SUPCTS)
|
||||
;
|
||||
; RESTORE BOOT CONSOLE CONFIGURATION
|
||||
;
|
||||
CALL LDELAY ; ALLOW SERIAL PORT TO FLUSH
|
||||
LD B,BF_CIOINIT ; HBIOS CIO INIT
|
||||
LD A,(HB_BOOTCONSAV) ; ORIGINAL BOOT CONSOLE DEVICE
|
||||
LD C,A ; BOOT CONSOLE TO C
|
||||
LD DE,(HB_CONCFGSAV) ; SAVED ORIGINAL CONSOLE CFG
|
||||
CALL HB_DISPATCH ; INTERNAL HBIOS CALL
|
||||
;
|
||||
#ENDIF
|
||||
;
|
||||
; IF WE ARE GOING TO SWITCH CONSOLES, IT IS IMPLEMENTED HERE. A
|
||||
; MESSAGE IS PRINTED ON THE OLD CONSOLE INDICATING WHERE THE NEW
|
||||
; CONSOLE IS AND THE NEW CONSOLE RECEIVES AN HBIOS BANNER.
|
||||
@@ -5380,10 +5439,10 @@ HB_BADINTCNT .DB 0
|
||||
LD A,L
|
||||
RRCA
|
||||
RRCA
|
||||
CALL PRTHEXBYTE
|
||||
PRTS("H: $")
|
||||
|
||||
;CALL PRTHEXBYTE
|
||||
;PRTS("H: $")
|
||||
CALL XREGDMP
|
||||
CALL NEWLINE
|
||||
;CALL CONTINUE
|
||||
OR $FF ; SIGNAL INTERRUPT HANDLED
|
||||
RET
|
||||
@@ -7721,6 +7780,11 @@ HB_BOOTCON .DB 0 ; INITIAL BOOT CONSOLE SAVE AREA
|
||||
HB_BOOTCFG .DW 0 ; CONSOLE CONFIG SAVE AREA
|
||||
HB_NEWCON .DB 0 ; NEW CONSOLE TO SWITCH TO
|
||||
;
|
||||
#IF (SUPCTS)
|
||||
HB_BOOTCONSAV .DB 0 ; INITIAL BOOT CONSOLE SAVE AREA
|
||||
HB_CONCFGSAV .DW 0 ; CONSOLE CONFIG SAVE AREA
|
||||
#ENDIF
|
||||
;
|
||||
HB_HASFP .DB 0 ; NON-ZERO MEANS FP EXISTS
|
||||
;
|
||||
HB_WRKBUF .FILL 512,0 ; INTERNAL DISK BUFFER
|
||||
|
||||
@@ -303,6 +303,14 @@ BE_AGAIN:
|
||||
BE_END:
|
||||
HB_EI
|
||||
POP IX
|
||||
;
|
||||
; Above flow flips the speaker bit an odd number of times which
|
||||
; leaves the bit set to the opposite value it started at. This
|
||||
; ensures that the bit is properly reset to its original value.
|
||||
;
|
||||
LD A,(HB_RTCVAL) ; Get the current RTC latch value
|
||||
OUT (RTCIO),A ; Set it
|
||||
;
|
||||
RET ; ALWAYS EXITS WITH SUCCESS STATUS (A=0)
|
||||
;
|
||||
;======================================================================
|
||||
|
||||
@@ -837,7 +837,7 @@ INT_CTC0A .EQU 0 ; ZILOG CTC 0, CHANNEL A
|
||||
INT_CTC0B .EQU 1 ; ZILOG CTC 0, CHANNEL B
|
||||
INT_CTC0C .EQU 2 ; ZILOG CTC 0, CHANNEL C
|
||||
INT_CTC0D .EQU 3 ; ZILOG CTC 0, CHANNEL D
|
||||
;INT_SIO0 .EQU 7 ; ZILOG SIO 0, CHANNEL A & B
|
||||
INT_SIO0 .EQU 6 ; ZILOG SIO 0, CHANNEL A & B
|
||||
INT_SIO1 .EQU 8 ; ZILOG SIO 1, CHANNEL A & B
|
||||
INT_PIO0A .EQU 9 ; ZILOG PIO 0, CHANNEL A
|
||||
INT_PIO0B .EQU 10 ; ZILOG PIO 0, CHANNEL B
|
||||
|
||||
@@ -59,11 +59,16 @@ UARTSBASE .EQU $58
|
||||
#ELSE
|
||||
UARTSBASE .EQU $68
|
||||
#ENDIF
|
||||
UARTABASE .EQU $A8
|
||||
UARTCBASE .EQU $80
|
||||
UARTMBASE .EQU $18
|
||||
UART4BASE .EQU $C0
|
||||
UARTRBASE .EQU $A0
|
||||
#IF (PLATFORM == PLT_DUO)
|
||||
UARTDBASE .EQU $70
|
||||
#ELSE
|
||||
UARTDBASE .EQU $80
|
||||
#ENDIF
|
||||
;
|
||||
#IF (UARTINTS)
|
||||
;
|
||||
@@ -1037,6 +1042,16 @@ UART_CFG_SBC:
|
||||
.DW UARTCFG ; LINE CONFIGURATION
|
||||
.DW UARTSBC_RCVBUF ; POINTER TO RCV BUFFER STRUCT
|
||||
#ENDIF
|
||||
#IF (UARTAUX)
|
||||
UART_CFG_AUX:
|
||||
; AUX SERIAL PORT
|
||||
.DB 0 ; DEVICE NUMBER (UPDATED DURING INIT)
|
||||
.DB 0 ; UART TYPE
|
||||
.DB UARTABASE ; IO PORT BASE (RBR, THR)
|
||||
.DB UARTABASE + UART_LSR ; LINE STATUS PORT (LSR)
|
||||
.DW UARTCFG ; LINE CONFIGURATION
|
||||
.DW 0 ; NO INT HANDLER
|
||||
#ENDIF
|
||||
#IF (UARTCAS)
|
||||
UART_CFG_CAS:
|
||||
; CASSETTE INTERFACE SERIAL PORT
|
||||
|
||||
@@ -407,8 +407,8 @@ XREGDMP:
|
||||
|
||||
LD (REGDMP_SP),SP ; SAVE STACK POINTER
|
||||
|
||||
;LD (RD_STKSAV),SP ; SAVE ORIGINAL STACK POINTER
|
||||
;LD SP,RD_STACK ; SWITCH TO PRIVATE STACK
|
||||
LD (RD_STKSAV),SP ; SAVE ORIGINAL STACK POINTER
|
||||
LD SP,RD_STACK ; SWITCH TO PRIVATE STACK
|
||||
|
||||
PUSH AF
|
||||
PUSH BC
|
||||
@@ -462,7 +462,7 @@ XREGDMP:
|
||||
POP BC
|
||||
POP AF
|
||||
|
||||
;LD SP,(RD_STKSAV) ; BACK TO ORIGINAL STACK FRAME
|
||||
LD SP,(RD_STKSAV) ; BACK TO ORIGINAL STACK FRAME
|
||||
|
||||
JP $FFFF ; RETURN, $FFFF IS DYNAMICALLY UPDATED
|
||||
REGDMP_RET .EQU $-2 ; RETURN ADDRESS GOES HERE
|
||||
@@ -470,9 +470,9 @@ REGDMP_RET .EQU $-2 ; RETURN ADDRESS GOES HERE
|
||||
REGDMP_PC .DW 0
|
||||
REGDMP_SP .DW 0
|
||||
;
|
||||
;RD_STKSAV .DW 0
|
||||
; .FILL $FF,16*2 ; 16 LEVEL PRIVATE STACK
|
||||
;RD_STACK .EQU $
|
||||
RD_STKSAV .DW 0
|
||||
.FILL $FF,16*2 ; 16 LEVEL PRIVATE STACK
|
||||
RD_STACK .EQU $
|
||||
;
|
||||
;
|
||||
;
|
||||
|
||||
Binary file not shown.
@@ -17,6 +17,11 @@ FLASH4 has been tested and confirmed working on:
|
||||
It should work on many other machines that run RomWBW or UNA BIOS. If you test
|
||||
it on another machine please let me know the outcome.
|
||||
|
||||
FLASH030 (also included) is a Linux version of the same software. It is
|
||||
targetted at my 68030 machine but should be very easy to port to other
|
||||
machines. It expects a machine with a larger address space, and thus omits much
|
||||
of the bank switching and other tricks required on Z80 platforms.
|
||||
|
||||
|
||||
= Introduction =
|
||||
|
||||
|
||||
Binary file not shown.
@@ -1,282 +1,112 @@
|
||||
File: UNARC.DOC
|
||||
Subject: User Documentation for UNARC Program
|
||||
Version: 1.6
|
||||
Date: March 27, 1987
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
|
||||
UNARC
|
||||
|
||||
CP/M Archive File Extraction Utility
|
||||
|
||||
|
||||
Copyright (C) 1986, 1987 by Robert A. Freed
|
||||
All Rights Reserved
|
||||
|
||||
|
||||
|
||||
This file provides user-level documentation and operating instructions for
|
||||
UNARC version 1.6, released March 27, 1987. Refer to the notice at the end of
|
||||
this file regarding rights of use and distribution of this program.
|
||||
|
||||
The release message file, UNARC.MSG, provides a list of all additional files
|
||||
distributed with the current UNARC release and describes the program changes
|
||||
from the previous version 1.4 and 1.5 releases.
|
||||
|
||||
|
||||
|
||||
ABSTRACT
|
||||
--------
|
||||
|
||||
UNARC is a utility program for CP/M systems which allows the listing, typeout,
|
||||
printing, checking, and extraction of subfiles contained in "archive" library
|
||||
(*.ARC or *.ARK) files. These are commonly used for compressed file storage
|
||||
on remote access bulletin board systems. UNARC provides the CP/M user the
|
||||
ability to process such files after downloading them via modem from these
|
||||
remote systems.
|
||||
|
||||
|
||||
|
||||
REQUIREMENTS
|
||||
------------
|
||||
|
||||
UNARC requires CP/M version 2 or higher. The program is offered in two
|
||||
versions. The standard version, UNARC.COM, requires a Z80 processor (or
|
||||
compatible equivalent, e.g. HD64180 or NSC800). An alternate version,
|
||||
UNARCA.COM, is provided for systems with 8080 or 8085 processors (or 16-bit
|
||||
systems using the NEC V20 for CP/M emulation). Identical capabilities are
|
||||
provided by the two program versions.
|
||||
|
||||
NOTE
|
||||
|
||||
Although UNARCA.COM can execute on ANY system capable of
|
||||
supporting CP/M, it is larger and significantly slower than
|
||||
UNARC.COM and should be avoided by users of Z80-based systems.
|
||||
|
||||
UNARC is written in Z80 assembly language and requires only 5K bytes of disk
|
||||
storage (6K for UNARCA). As distributed, the program requires at least 30K
|
||||
bytes of available memory space (TPA) for full support of all archive file
|
||||
formats (31K TPA size for UNARCA). (Smaller systems may be able to use some
|
||||
of the program's capabilities.)
|
||||
|
||||
|
||||
|
||||
ABOUT ARC/ARK FILES
|
||||
-------------------
|
||||
|
||||
The files which UNARC processes utilize a format that was introduced by the
|
||||
ARC shareware utility program, which executes on 16-bit computers running the
|
||||
MS-DOS (or PC-DOS) operating system. This format has achieved widespread
|
||||
popularity since the ARC program first appeared in March 1985, and it has
|
||||
become the de facto standard for file storage on remote access systems
|
||||
catering to 16-bit computer users. More recently this file format has
|
||||
achieved increased popularity on RCP/M (Remote CP/M) systems.
|
||||
|
||||
NOTE
|
||||
|
||||
Most RCP/M system operators have adopted the convention of naming
|
||||
CP/M archive files with the filetype ARK. This differentiates
|
||||
these from MS-DOS archive files, which use the filetype ARC. This
|
||||
is a naming convention only: There is no difference in format,
|
||||
and UNARC will accept files of either type interchangeably.
|
||||
|
||||
An archive is a group of files collected together into a single file in such a
|
||||
way that the individual files may be recovered intact. In this respect,
|
||||
archives are similar in function to libraries (*.LBR files), which have been
|
||||
commonplace on CP/M systems since 1982, when the original LU library utility
|
||||
program was introduced by Gary P. Novosielski. (However, the two file formats
|
||||
are not compatible.)
|
||||
|
||||
The distinguishing characteristic of an ARC archive is that its component
|
||||
files are automatically compressed when they are added to the archive, so that
|
||||
the resulting file occupies a minimum amount of disk space. Of course, file
|
||||
compression techniques have also been commonplace in the CP/M world since
|
||||
1981, when the public domain SQ and USQ "squeeze and unsqueeze" programs were
|
||||
introduced by Richard Greenlaw.
|
||||
|
||||
The SQ/USQ programs and their numerous popular descendants utilize a well-
|
||||
known general-purpose form of data compression (Huffman coding). This
|
||||
technique, which is also utilized in ARC files, performs well for many text
|
||||
files but often produces poor compression of binary files (e.g. object program
|
||||
.COM files). The ARC program also provides an advanced data compression
|
||||
method, which it terms "crunching." This method (which is based on the
|
||||
Lempel-Ziv-Welch or "LZW" algorithm) performs better than squeezing in most
|
||||
cases, often achieving 50% or better compression of ASCII text files, 15-40%
|
||||
compression of binary object files, and as much as 95% compression of bit-
|
||||
mapped graphics image files.
|
||||
|
||||
Five different methods are actually employed for storing files in an archive.
|
||||
The method chosen for a particular file is the one which results in the best
|
||||
compression for that file:
|
||||
|
||||
(1) No compression ("unpacked"). The file is stored in its original form.
|
||||
|
||||
(2) Run-length encoding ("packed"). Repeated sequences of 3-255 identical
|
||||
bytes are compressed into a three-byte sequence.
|
||||
|
||||
(3) Huffman coding ("squeezed"). Each 8-bit byte (after run-length encoding)
|
||||
is encoded by a variable number of bits, with bit length (approximately)
|
||||
inversely proportional to the frequency of occurence of the corresponding
|
||||
byte.
|
||||
|
||||
(4) LZW compression ("crunched"). Variable-length strings of bytes (in
|
||||
theory, up to nearly 4000 bytes in length) are represented by a single
|
||||
(maximum) 12-bit code (after run-length encoding).
|
||||
|
||||
(5) LZW compression ("squashed"). This is a variation of crunching which
|
||||
uses (maximum) 13-bit codes (and no run-length encoding).
|
||||
|
||||
Note that since one of the five methods involves no compression at all, the
|
||||
resulting archive entry will never be larger than the original file.
|
||||
|
||||
NOTE
|
||||
|
||||
The most recent release of the MS-DOS ARC program (version 5.20)
|
||||
has eliminated squeezing as a compression technique. However,
|
||||
UNARC continues to process squeezed files for compatibility with
|
||||
archives created by earlier versions of ARC and by other MS-DOS
|
||||
archiving programs (notably PKARC).
|
||||
|
||||
The squashed compression method was recently introduced by the
|
||||
MS-DOS programs PKARC and PKXARC. UNARC can process files which
|
||||
use this method, although it is not universally accepted by other
|
||||
MS-DOS archive extraction programs (including ARC).
|
||||
|
||||
During its lifetime, the ARC program has undergone numerous revisions which
|
||||
have employed different variations on some of the above methods, particularly
|
||||
LZW compression. In order to retain compatibility with archives created by
|
||||
earlier program revisions, ARC stores a "version" indicator with each file in
|
||||
an archive. Based on this indicator, the latest release of the ARC program
|
||||
can always extract files created by older releases (although it will only use
|
||||
the latest data compression versions when adding new files to an archive).
|
||||
|
||||
NOTE
|
||||
|
||||
The current release of UNARC supports archive file versions
|
||||
generated by all releases of the following MS-DOS programs through
|
||||
(at least) the indicated program versions:
|
||||
|
||||
ARC 5.20 (24 Oct 86), by System Enhancement Associates, Inc.
|
||||
ARCA 1.22 (13 Sep 86), by Wayne Chin and Vernon Buerg
|
||||
ARCH 5.38 (26 Jun 86), by Les Satenstein
|
||||
PKARC 2.0 (15 Dec 86), by Phil Katz (PKWARE, Inc.)
|
||||
|
||||
(UNARC does not recognize, but is unaffected by, the non-standard
|
||||
archive and file commenting feature of PKARC.)
|
||||
|
||||
Although the above discussion has emphasized the origin of archive files for
|
||||
the MS-DOS operating system, their use has recently spread to many other
|
||||
systems. Programs compatible with MS-DOS ARC have appeared for UNIX, Atari
|
||||
68000, VAX/VMS, and TOPS-20 systems. A CP/M utility for building archive
|
||||
files will also be available in the near future.
|
||||
|
||||
For additional information about archive files and the MS-DOS ARC utility,
|
||||
refer to the documentation file, ARC.DOC, which is available from most remote
|
||||
access systems which utilize archive files. For additional information about
|
||||
the LZW algorithm (and data compression methods in general), refer to the
|
||||
article "A Technique for High-Performance Data Compression", by Terry A.
|
||||
Welch, in IEEE Computer magazine, Vol. 17, No. 6, June 1984.
|
||||
|
||||
|
||||
|
||||
USING UNARC
|
||||
-----------
|
||||
|
||||
The UNARC program provides an on-line help message, which is generated by
|
||||
running the program with an empty command line:
|
||||
|
||||
|
||||
A>UNARC
|
||||
|
||||
UNARC 1.6 27 Mar 87
|
||||
CP/M Archive File Extractor
|
||||
|
||||
Usage: UNARC [d:]arcfile[.typ] [d:][afn] [N|P|C]
|
||||
|
||||
Examples:
|
||||
B>UNARC A:SAVE.ARK *.* ; List all files in CP/M archive SAVE on drive A
|
||||
B>UNARC A:SAVE.ARC *.* ; List all files in MS-DOS archive SAVE on drive A
|
||||
A>UNARC SAVE ; Same as either of above
|
||||
A>UNARC SAVE *.* N ; Same as above (no screen pauses)
|
||||
A>UNARC SAVE *.DOC ; List just .DOC files
|
||||
A>UNARC SAVE READ.ME ; Typeout the file READ.ME
|
||||
A>UNARC SAVE READ.ME N ; Typeout the file READ.ME (no screen pauses)
|
||||
A>UNARC SAVE A: ; Extract all files to drive A
|
||||
A>UNARC SAVE B:*.DOC ; Extract .DOC files to drive B
|
||||
A>UNARC SAVE C:READ.ME ; Extract file READ.ME to drive C
|
||||
A>UNARC SAVE PRN.DAT P ; Print the file PRN.DAT (no formatting)
|
||||
A>UNARC SAVE *.* C ; Check validity of all files in archive
|
||||
|
||||
|
||||
As shown by this help display, the UNARC utility provides the following
|
||||
capabilities:
|
||||
|
||||
(1) Listing the directory of an archive
|
||||
(2) Extracting component files from an archive
|
||||
(3) Typing the contents of a component file at the console
|
||||
(4) Printing a component file directly on the CP/M list device
|
||||
(5) Checking the validity of an archive and its component files
|
||||
|
||||
The particular operation to be performed is determined by the form of the file
|
||||
parameter(s) in the command line, as described separately in the sections
|
||||
which follow. The following characteristics apply to all operations:
|
||||
|
||||
The first command line parameter must specify the name of an archive file. A
|
||||
drive name and filetype are optional. The filetype, if omitted, defaults to
|
||||
"ARK" or, if no such file exists, the alternate (MS-DOS) default "ARC" is
|
||||
assumed.
|
||||
|
||||
The standard CP/M terminal control characters, CTRL-S (to suspend console
|
||||
output) and CTRL-C (to abort the program), may be used at any time. CTRL-K
|
||||
may also be used as an alternate for CTRL-C. Printer output to the CP/M list
|
||||
device may be obtained by typing CTRL-P at CCP command level before executing
|
||||
UNARC.
|
||||
|
||||
In addition, by default UNARC will pause after every 23 lines of console
|
||||
output. At this time, the message "[more]" will appear at the bottom of the
|
||||
console screen. The listing may be resumed by typing any key (other than
|
||||
CTRL-S, CTRL-C, or CTRL-K, which will function as described above). If the
|
||||
space bar is used, one more line of console output will be displayed (over-
|
||||
writing the "[more]" message) and the program will again pause. If any other
|
||||
key is typed (e.g. RETURN), another 23 lines of output will be allowed to
|
||||
scroll onto the screen before the next pause. (LINE FEED may be used to
|
||||
prevent overprinting of the "[more]" line, e.g. for hard-copy terminals.)
|
||||
|
||||
If continuous display is desired, this automatic pause feature may be disabled
|
||||
by specifying "N" at the end of the command line. The "N" must be the last
|
||||
command line character, and it must be preceded by a space. Also, there must
|
||||
be two preceding file parameters on the command line. E.g., note the
|
||||
difference between the following commands:
|
||||
|
||||
A>UNARC SAVE N ; Typeout the file N. in archive SAVE
|
||||
A>UNARC SAVE *.* N ; List all files in archive SAVE with no pauses
|
||||
|
||||
The N option may not be used in conjunction with the P (Print) or C (Check)
|
||||
options.
|
||||
|
||||
|
||||
|
||||
LISTING AN ARCHIVE DIRECTORY
|
||||
----------------------------
|
||||
|
||||
By default, UNARC produces a detailed console listing of the component files
|
||||
in an archive. (In fact, there is no way to suppress this listing; it is
|
||||
generated during all UNARC operations.) If only the archive file name appears
|
||||
on the command line, UNARC will generate a complete directory of all component
|
||||
files in the specified archive file. Otherwise, the second command line
|
||||
parameter may be used to select a particular file to be listed (or group of
|
||||
files, if it contains the ambiguous file specification characters "*" or "?").
|
||||
If no disk drive name is provided for the second parameter, and this parameter
|
||||
specifies a group of files, the directory listing is the only output generated
|
||||
by the program.
|
||||
|
||||
A sample directory listing is illustrated here:
|
||||
|
||||
|
||||
A>UNARC CODES
|
||||
|
||||
Archive File = CODES.ARK
|
||||
|
||||
UNARCU
|
||||
Universal Archive File Extraction Utility
|
||||
Version 1.0
|
||||
|
||||
Modified for Universal use by Lars Nelson
|
||||
September 17, 2023
|
||||
Modified for ZCPR3 by Gene Pizzetta
|
||||
December 9, 1990
|
||||
Original CP/M 2.2 version is
|
||||
Copyright (C) 1986, 1987 by Robert A. Freed
|
||||
All Rights Reserved
|
||||
|
||||
|
||||
UNARCU allows the listing, typeout, printing, checking, and extraction of
|
||||
member files contained in ARK and ARC archive files. These are commonly
|
||||
used for compressed file storage on remote access bulletin boards. This is
|
||||
a universal version and runs on the following CP/M compatible systems:
|
||||
|
||||
CP/M 2.2 with DRI CCP or ZCPRD&J
|
||||
ZSDOS 1.2 and 2.0 with DRI CCP, ZCPRD&J or Zsystem
|
||||
CP/M 3 with DRI CCP or Z3Plus
|
||||
ZPM3 with DRI CCP or ZCCP
|
||||
|
||||
DU file specification is supported on all systems. If Zsystem is active
|
||||
then named directories can be used and the bad directories flag is
|
||||
automatically checked.
|
||||
|
||||
If datestamping is available then extracted files will recieve the ARK file's
|
||||
stored date stamp. The program handles DateStamper, NZTIME and CP.M Plus
|
||||
date stamping methods.
|
||||
|
||||
UNARCU requires at least 32K of free memory (TPA) for full support of all
|
||||
archive file formats, but smaller systems may be able to use some of the
|
||||
program's capabilities.
|
||||
|
||||
USAGE:
|
||||
|
||||
UNARCU {DU: or dir:}arcfile{.typ} {DU: or dir:}{afn.aft} {{/}options}
|
||||
|
||||
If a DIR or DU specification is not given for the archive file, the current
|
||||
drive/user is assumed. The second filename, which can be ambiguous,
|
||||
refers to a member file or files in the archive. DIR: file specification
|
||||
only available when Zsystem is active. DU: specification always available.
|
||||
|
||||
If a DU or DIR specification is provided for the member filespec, it will be
|
||||
extracted to that directory. To extract to the current directory, only a
|
||||
colon is required. If a directory specification is given without a filename,
|
||||
all files ("*.*") is assumed.
|
||||
|
||||
If no DU or DIR specification is given, UNARCU acts differently depending
|
||||
on whether the member name is ambiguous or not. If the member name is
|
||||
unambiguous, and the filetype is not restricted, the file will be typed to
|
||||
the screen. If the member name is ambiguous, or if no member name is
|
||||
given at all, a directory of the ARK will be displayed.
|
||||
|
||||
If no filetype is given for the archive file, UNARCU first tries ARK and then
|
||||
ARC.
|
||||
|
||||
An on-line help message will be displayed if UNARCU is called with no
|
||||
command tail or if the command tail is "//".
|
||||
|
||||
OPTIONS: Options may or may not be preceded by a slash, but the slash is
|
||||
required if the options are not the third token (element) on the command
|
||||
line.
|
||||
|
||||
C Check the validity of the archive and the given member
|
||||
files. If a member filespec is not given, all files
|
||||
("*.*") is assumed.
|
||||
|
||||
E Toggle erasing of existing files without asking on and
|
||||
off. UNARCU may be configured to automatically erase,
|
||||
during member file extraction, existing files in the
|
||||
target directory that have the same name. Or it can
|
||||
be configured to ask first. This option will turn off
|
||||
user query before erasure, if it is on by default, and
|
||||
vice versa.
|
||||
|
||||
N Toggle console paging on or off. UNARCU may be
|
||||
configured to default to console paging or not. This
|
||||
option will turn paging off, if the the default is on,
|
||||
and vice-versa. Paging effects both archive directory
|
||||
display and member file type-out. During member file
|
||||
extraction, console paging is always off.
|
||||
|
||||
P Sends a member file to the printer (LST device). The
|
||||
member name cannot be ambiguous. The file will be
|
||||
printed continuously, with no formatting or paging.
|
||||
|
||||
UNARCU can be aborted at any time with ^C or ^K.
|
||||
|
||||
If screen paging is enabled, UNARCU pauses after the screen fills. The
|
||||
listing may be resumed by typing any key other than ^S, ^C, or ^K. The
|
||||
space bar displays one more line of output (overwriting the "[more]"
|
||||
message) and the program will again pause. For hard copy terminals, line
|
||||
feed may be used to prevent overprinting of the "[more]" line. If paging
|
||||
is disabled, the display can be paused with ^S.
|
||||
|
||||
LISTING AN ARCHIVE DIRECTORY: UNARC always produces a detailed
|
||||
console listing of all the member files of an archive, or of those members
|
||||
which match the second file specification, if one is given. If no member
|
||||
name is given, or if the member name is ambiguous, then UNARCU only lists
|
||||
the directory, without doing anything else. (That is, unless the C option is
|
||||
included.)
|
||||
|
||||
A sample directory listing:
|
||||
|
||||
A0>UNARCU CODES
|
||||
Archive File = A0:CODES.ARK
|
||||
Name Length Disk Method Ver Stored Saved Date Time CRC
|
||||
============ ======= ==== ======== === ======= ===== ========= ====== ====
|
||||
ABLE .DOC 24320 24k Crunched 8 11777 52% 30 Apr 86 10:50a 42C0
|
||||
@@ -285,97 +115,82 @@ CHARLIE .TXT 234 1k Packed 3 99 58% 2 May 86 4:11p 8927
|
||||
==== ======= ==== ======= === ====
|
||||
Total 3 41706 42k 26626 36% 58A4
|
||||
|
||||
The listing is equivalent to the "verbose" listing of the MS-DOS ARC
|
||||
program, with the addition of the "Disk" and "Ver" fields, which are unique
|
||||
to UNARCU and previous UNARC versions. The listing requires 78-columns
|
||||
of terminal width.
|
||||
|
||||
This listing is equivalent to the "verbose" listing of the MS-DOS ARC program
|
||||
(with the addition of the "Disk" and "Ver" fields, which are unique to UNARC).
|
||||
The listing requires a 78-column terminal width; there is currently no "short"
|
||||
listing format.
|
||||
"Name" is the filename which will be generated if the file is extracted by
|
||||
UNARCU. This is not necessarily the same as the name recorded in the
|
||||
archive file. Although CP/M and MS-DOS file naming conventions are
|
||||
identical, two conversions are made to guarantee filename validity: Lower-
|
||||
case letters are converted to upper-case and non-printing characters are
|
||||
converted to dollar signs ("$"). Archive entries are usually maintained and
|
||||
listed in alphabetical order.
|
||||
|
||||
"Name" is the file name which will be generated if the file is extracted by
|
||||
UNARC on a CP/M system. (This is not necessarily the same as the name
|
||||
recorded in the archive file. Although CP/M and MS-DOS file naming
|
||||
conventions are identical, two conversions are made to guarantee file name
|
||||
validity under CP/M: Lower-case letters are converted to upper-case, and
|
||||
non-printing characters are converted to dollar signs, "$".) Archive entries
|
||||
are usually maintained (and hence listed) in alphabetic name order.
|
||||
"Length" is the uncompressed file length, i.e., the number of bytes the file
|
||||
will occupy if extracted to disk, exclusive of any additional length imposed
|
||||
by the file system. MS-DOS permits files of arbitrary lengths, but CP/M
|
||||
restricts files to multiples of 128 bytes.
|
||||
|
||||
"Length" is the uncompressed file length, i.e. the number of bytes the file
|
||||
will occupy if extracted to disk, exclusive of any additional length imposed
|
||||
by the CP/M file system. Note that MS-DOS permits files of arbitrary lengths
|
||||
(unlike CP/M which restricts all files to a multiple of 128 bytes).
|
||||
"Disk" is the actual amount of space required to extract the file to a CP/M
|
||||
disk, expressed as a multiple of 1K (1024) bytes. The number is dependent
|
||||
on the output drive's allocation block size, which can range from 1K to 16K
|
||||
bytes. Typically, 1K is used for single-density floppy disks, 2K for
|
||||
double-density floppies, and 4K for hard disks. In the absence of an
|
||||
explicit output drive, UNARCU uses the block size of the currently logged
|
||||
drive, or a configured default size.
|
||||
|
||||
"Disk" is the actual amount of disk space required to extract the file to a
|
||||
CP/M disk, expressed as a multiple of 1K (1024) bytes. Note that this number
|
||||
is dependent on the disk data allocation block size. (CP/M permits various
|
||||
block sizes, ranging from 1K to 16K bytes. Typical sizes are 1K for single-
|
||||
density floppy disks, 2K for double-density floppies, and 4K for hard disks,
|
||||
although these values are quite system-dependent.) In the absence of an
|
||||
explicit output drive name, UNARC uses the block size of the default
|
||||
(currently "logged") disk drive (i.e. the drive which appears in the CCP
|
||||
prompt).
|
||||
"Method" is the compression method used: "Unpacked", "Packed",
|
||||
"Squeezed", "Crunched", "Squashed", or "Unknown!". If the method
|
||||
"Unknown!" appears, it likely indicates a faulty archive file or a newer
|
||||
compression method not yet supported by UNARCU.
|
||||
|
||||
"Method" is the compression method used, specified as "Unpacked", "Packed",
|
||||
"Squeezed", "Crunched", "Squashed", or "Unknown!". If the method "Unknown!"
|
||||
appears, it most likely indicates (if not a faulty archive file) a newer
|
||||
release of the MS-DOS ARC program that supports a new compression method (or a
|
||||
new variation of an existing method). In this case, a corresponding new
|
||||
release of UNARC will be required to extract the file.
|
||||
"Ver" is the version of compression method used. UNARC supports versions
|
||||
1-9: unpacked files, versions 1 or 2; packed files, version 3; squeezed
|
||||
files, version 4; crunched files, versions 5 and squashed files, version 9.
|
||||
|
||||
"Ver" further identifies the version of compression used. Currently, UNARC
|
||||
supports versions 1-9: unpacked files can have versions 1 or 2; packed files,
|
||||
version 3; squeezed files, version 4; crunched files, versions 5-8; and
|
||||
squashed files, version 9. The highest version number associated with each
|
||||
compression method is the one generated by the most recent release of the
|
||||
MS-DOS ARC program.
|
||||
"Stored" is the compressed file length, that is, the number of bytes
|
||||
occupied by the file in the archive, not including the directory information
|
||||
overhead, which adds an additional 29 bytes to each member file.
|
||||
|
||||
"Stored" is the compressed file length, i.e. the number of bytes occupied by
|
||||
the file in the archive. (This does not include the overhead associated with
|
||||
the directory information itself, which adds an additional 29 bytes to the
|
||||
size of each component file.)
|
||||
|
||||
"Saved" is the percentage of the original file length which was saved by
|
||||
compression; i.e., higher values indicate better compression. (The MS-DOS ARC
|
||||
documentation refers to this as the "stowage factor.") The value shown on the
|
||||
totals line applies to the archive as a whole, not including the directory
|
||||
"Saved" indicates the percentage of the original file length which was saved
|
||||
by compression. Higher values indicate better compression. The MS-DOS
|
||||
ARC documentation refers to this as the "stowage factor". The value shown
|
||||
in the totals applies to the archive as a whole, excluding directory
|
||||
overhead.
|
||||
|
||||
"Date" and "Time" refer to the last file modification, as of the time it was
|
||||
added to the archive. (Date and time stamping is, of course, one of the nice
|
||||
features of MS-DOS which is lacking in standard CP/M 2.2.)
|
||||
"Date" and "Time" are the file modification stamp at the time it was added
|
||||
to the archive.
|
||||
|
||||
"CRC" is an internal 16-bit cyclic redundancy check value which is computed
|
||||
when a file is added to an archive (expressed in hexadecimal). As a test of
|
||||
file validity, UNARC re-computes this value when it extracts a file (see
|
||||
below). Note that this value is calculated by a different method than that
|
||||
used by either of the two popular public domain programs, CRCK and CHEK. (It
|
||||
is however quite valid as a reliable error-detection mechanism.) This value
|
||||
is shown in the listing for completeness only. The value shown on the totals
|
||||
line is the 16-bit sum of all displayed CRC values. This is useful as a
|
||||
single "checksum" value for comparing entire archives. (Since the CRC values
|
||||
are computed before compression takes place, the total should be the same for
|
||||
all archives created from the same set of input files, independent of any
|
||||
particular variations in file order or compression methods.)
|
||||
"CRC" is an internal 16-bit cyclic redundancy check value computed when a
|
||||
file is added to an archive, expressed in hexadecimal. UNARCU checks file
|
||||
validity by recomputing this value when it extracts a file. The value is
|
||||
calculated by a different method than that used by either of the two
|
||||
popular public domain programs, CRCK and CHEK, but it is a quite valid and
|
||||
reliable error-detection mechanism. The value is given for completeness
|
||||
only. The total in the last line is the 16-bit sum of the displayed CRC
|
||||
values and is useful for comparing entire archives. Since the CRC values
|
||||
are computed before compression, the total should be the same for all
|
||||
archives created from the same set of input files, without regard for
|
||||
variations in file order or compression methods.
|
||||
|
||||
The "Total" line is displayed only if multiple files appear in the listing,
|
||||
and it includes a count of the number of files listed.
|
||||
The "Total" line is displayed only if more than one file appears in the
|
||||
listing.
|
||||
|
||||
EXTRACTING FILES FROM AN ARCHIVE: If the second command line
|
||||
parameter contains a DU or DIR specification UNARCU will extract the
|
||||
selected member file or files to to the indicated disk directory. If the
|
||||
directory specification is given without a filename, all member files will be
|
||||
extracted to the indicated directory. If only a colon is given, the current
|
||||
drive/user will be assumed.
|
||||
|
||||
Below is a directory listing as might be generated during file extraction,
|
||||
along with some possible warning messages:
|
||||
|
||||
EXTRACTING FILES FROM AN ARCHIVE
|
||||
--------------------------------
|
||||
|
||||
If the second command line parameter contains a disk drive name, UNARC will
|
||||
extract the selected file(s) from the archive to CP/M file(s) on the indicated
|
||||
disk drive. If only a drive name appears, all component files of the archive
|
||||
will be extracted. The following illustrates a sample archive directory
|
||||
listing as generated during a file extraction operation:
|
||||
|
||||
|
||||
A>UNARC CODES B:
|
||||
|
||||
Archive File = CODES.ARK
|
||||
Output Drive = B:
|
||||
|
||||
A0>UNARCU CODES B1:
|
||||
Archive File = A0:CODES.ARK
|
||||
Output Directory = B1:
|
||||
Name Length Disk Method Ver Stored Saved Date Time CRC
|
||||
============ ======= ==== ======== === ======= ===== ========= ====== ====
|
||||
ABLE .DOC 24320 24k Crunched 8 11777 52% 30 Apr 86 10:50a 42C0
|
||||
@@ -388,236 +203,235 @@ CHARLIE .TXT 234 2k Packed 3 99 58% 2 May 86 4:11p 8927
|
||||
==== ======= ==== ======= === ====
|
||||
Total 3 41706 44k 26616 36% 58A4
|
||||
|
||||
"Replace existing output file (y/n)?" appears if a file of the same name
|
||||
exists in the output directory, requiring a "Y" or "N" response. Any
|
||||
response other than "Y" will be consided to be the same as "N". If UNARCU
|
||||
has been configured to erase without query, this message will not appear.
|
||||
|
||||
The above listing also illustrates several warning messages which may occur
|
||||
when extracting files from an archive.
|
||||
The first two of the "Warning:" messages above indicate that either the
|
||||
cyclic redundancy check (CRC) value or the extracted file length does not
|
||||
match the value recorded in the archive header when the original file was
|
||||
added. The third warning message is displayed if the proper format for
|
||||
the beginning of a new member is not detected, but UNARCU recovered by
|
||||
skipping a certain number of bytes in the archive file. If a recovery
|
||||
attempt fails, UNARC aborts and issues a different message, "Invalid archive
|
||||
file format". The appearance of any of these messages probably means the
|
||||
file data has been corrupted in some way.
|
||||
|
||||
The message "Replace existing output file (y/n)?" appears if a file of the
|
||||
same name already exists on the output drive. The user must answer "Y" (or
|
||||
"y") to allow the extraction to proceed (in which case, the existing file is
|
||||
unceremoniously deleted). Any other response will cause UNARC to preserve the
|
||||
existing file, bypass the extraction operation for the current file, and
|
||||
(except for a CTRL-C response) skip to the next file to be extracted (if any).
|
||||
If the original MS-DOS file length was not an exact multiple of 128 bytes,
|
||||
the final record of the extracted file will be padded with 1Ah characters
|
||||
(ASCII ^Z).
|
||||
|
||||
The first two warning messages illustrated above are provided as a check on
|
||||
the validity of the extracted file. These indicate that either the cyclic
|
||||
redundancy check (CRC) value computed by UNARC, or the resulting extracted
|
||||
file length, does not match the corresponding value recorded in the archive
|
||||
when the original file was added to it. The final warning message occurs if
|
||||
UNARC fails to detect the proper format for the start of a new subfile, but
|
||||
can recover by skipping a certain number of bytes in the archive file. (If
|
||||
the recovery attempt fails, UNARC aborts with the message "Invalid archive
|
||||
file format.") The appearance of any of these messages most likely indicates
|
||||
that the file data has been corrupted in some way (e.g. during modem
|
||||
transmission from a remote system).
|
||||
Disk space in the listing will be correct for the specified output directory.
|
||||
In the two examples above, drive A has 1K allocation blocks while drive B
|
||||
has a 2K blocks, which accounts for the differences in the two listings. To
|
||||
determine the exact disk space requirements before extracting files, log
|
||||
into the desired output drive and take an UNARCU directory listing of the
|
||||
ARK file.
|
||||
|
||||
Note that if the original (i.e. MS-DOS) file length was not an exact multiple
|
||||
of 128 bytes (as required by CP/M), UNARC will pad the final record of the
|
||||
extracted file with hex "1A" (ASCII CTRL-Z) bytes. This provides the correct
|
||||
end-of-file termination for text files, according to CP/M conventions.
|
||||
If a file extraction is aborted with ^C, any partial output file will have to
|
||||
be deleted manually.
|
||||
|
||||
Also, the disk space shown in the archive directory listing will be correct
|
||||
for the specified disk drive. (In the above examples, drive A: has a 1K data
|
||||
allocation block size while drive B: has a 2K block size, which accounts for
|
||||
the differences in the two listings.) In order to determine the exact disk
|
||||
space requirements in advance of a file extraction operation, the user may
|
||||
first "log into" the desired output drive (i.e. select it as the default
|
||||
drive), and run UNARC to obtain a directory listing only. (This is a
|
||||
consideration only on systems with mixed disk drive types.)
|
||||
|
||||
A file extraction operation may be aborted at any time by entering CTRL-C from
|
||||
the console. In this case, any partial output file will remain on disk and
|
||||
should be deleted manually following the program abort. (Any existing file of
|
||||
the same name will have already been deleted, however.)
|
||||
|
||||
|
||||
|
||||
TYPING OUT A FILE IN AN ARCHIVE
|
||||
-------------------------------
|
||||
|
||||
A console typeout of the contents of a single component file in an archive may
|
||||
be requested by specifying a non-ambiguous file name (and no disk drive name)
|
||||
in the second command line parameter. For example:
|
||||
|
||||
|
||||
A>UNARC CODES ABLE.DOC
|
||||
|
||||
Archive File = CODES.ARK
|
||||
TYPING MEMBER FILES: Typing the contents of a member file in an archive
|
||||
to the console may be requested by giving a non-ambiguous filename and no
|
||||
output disk directory as the second command line parameter. For example:
|
||||
|
||||
A0>UNARCU CODES ABLE.DOC
|
||||
Archive File = A0:CODES.ARK
|
||||
Name Length Disk Method Ver Stored Saved Date Time CRC
|
||||
============ ======= ==== ======== === ======= ===== ========= ====== ====
|
||||
ABLE .DOC 24320 24k Crunched 8 11777 52% 30 Apr 86 10:50a 42C0
|
||||
-------------------------------------------------------------------------------
|
||||
This is file ABLE.DOC, contained within the archive CODES.ARK. Typeout will
|
||||
proceed until the end of this file or may be aborted by CTRL-C.....
|
||||
proceed until the end of this file, so you'd better be patient. For somebody
|
||||
who has nothing to say, I've written an awfully big file here. If you don't
|
||||
want to read all 24K of it, you can type ^C ....
|
||||
|
||||
The specified file is assumed to contain valid ASCII text data. All bytes
|
||||
are masked to seven bits and all control characters are ignored except
|
||||
horizontal tabs, which are expanded to blanks with stops at every eighth
|
||||
column), and line feeds, vertical tabs, and form feeds, all of which generate
|
||||
a new line. SUB (^Z) is interpreted as the end of the file. Backspaces and
|
||||
carriage returns are ignored, so text will not be obscured.
|
||||
|
||||
UNARCU will refuse to type files whose filetype indicates are not ASCII text
|
||||
files, including COM, CMD, EXE, OBJ, OVL, REL, PRL, CRL, IRL, INI, SYS,
|
||||
BAD, ARK, ARC, LBR, ?Q?, ?Y? and ?Z?. If one of these or other restricted
|
||||
types is given, directory information only is listed.
|
||||
|
||||
CRC and file length checking are not performed when a file is typed to the
|
||||
screen.
|
||||
|
||||
PRINTING MEMBER FILES: A single member file may be sent to the printer
|
||||
(CP/M LST device) with the "P" option as the third parameter on the
|
||||
command line with or without a preceding slash. In addition, the member
|
||||
name must be non-ambiguous and must not be preceded by a drive or user
|
||||
specification. For example:
|
||||
A0>UNARCU CODES CHARLIE.TXT P
|
||||
or
|
||||
A0>UNARCU CODES CHARLIE.TXT /P
|
||||
|
||||
The contents of the specified file is passed directly to the printer without
|
||||
alteration, additional formatting, or even paging. The user should make
|
||||
sure it contains data suitable for printer output. This unfiltered operation
|
||||
is particularly well-suited for the output of binary graphics images to
|
||||
dot-matrix printers. These files can be extremely large, but compress quite
|
||||
well, often to less than 5% of their original size. The same filetypes
|
||||
excluded from typing are also excluded from printing. Printing may be
|
||||
paused or aborted with ^S and ^C respectively.
|
||||
|
||||
CHECKING MEMBER FILES: With the "C" option UNARCU can be directed to
|
||||
extract one or more member files from an archive, without actually storing
|
||||
them as disk files. This operation performs file CRC and length checking,
|
||||
so it is useful for verifying correct modem data transmission of an archive.
|
||||
If the "C" is the second parameter on the command line, it must be
|
||||
preceded by a slash. In that case all files in the archive will be checked.
|
||||
If a member filename is given, it may be ambiguous, but it cannot be
|
||||
preceded by a disk directory specification. For example:
|
||||
A0>UNARCU CODES *.DOC C
|
||||
or
|
||||
A0>UNARCU CODES /C
|
||||
|
||||
FILE DATE STAMPING: ARK and ARC files contain only a member file's
|
||||
modification date and time. When a member is extracted under ZSDOS or
|
||||
CP/M 3 with date stamping, its modification date will be transferred to disk
|
||||
as both the create and modification file date stamps. If the modification
|
||||
date is not included in the archive, then the extracted file will be stamped
|
||||
with the current date and time.
|
||||
|
||||
SECURITY: Z-Node security is handled automatically by UNARCU when
|
||||
Zsystem is running. If the Wheel byte is off (reset), file extraction,
|
||||
archive checking, and file printing are all disabled. In addition, UNARCU
|
||||
can be configured to disable file type-out or to limit type-out to a maximum
|
||||
number of lines.
|
||||
|
||||
|
||||
The specified file is assumed to contain valid ASCII text data. In
|
||||
particular, all bytes are masked to seven bits, and all ASCII control
|
||||
characters are ignored except for HT (horizontal tab, which is expanded to
|
||||
blanks with assumed tab stops at every eighth column), LF, VT or FF (line
|
||||
feed, vertical tab or form feed, which generate a new typeout line), and SUB
|
||||
(CTRL-Z, which by CP/M convention indicates end-of-file and terminates the
|
||||
typeout). Note that BS (backspace) and CR (carriage return) are ignored, so
|
||||
that text will not be obscured within files which utilize these for over-
|
||||
printing (i.e. when directed to a printer).
|
||||
Directory security depends on the file specification parsing of ZCPR 3.3 or
|
||||
higher to indicate that the DU or DIR are illegal. Security should be
|
||||
adequate, however, under other CPR's.
|
||||
|
||||
The following filetypes, which are usually associated with binary (non-text)
|
||||
data, are specifically excluded from typeout operations: COM, EXE, OBJ, OV?,
|
||||
REL, ?RL, INT, SYS, BAD, LBR, ARC, ARK, ?Q?, and ?Z?. If one of these types
|
||||
is specified, only the directory information for the requested file is listed.
|
||||
PROGRAM CONFIGURATION OPTIONS: Several configuration bytes are
|
||||
available to tailor the program for specific requirements, particularly for
|
||||
RCP/M systems. With the Wheel byte off, UNARCU can be used by remote
|
||||
callers only for archive directory listing and, optionally, for member file
|
||||
typeout.
|
||||
|
||||
Note that CRC and file length checking are not performed during a typeout
|
||||
operation, as they are during extraction to a disk file.
|
||||
Configuration bytes also determine the default conditions for the N and E
|
||||
command line options and the filetypes excluded from type-out.
|
||||
|
||||
Other configuration points are provided for non-standard systems and need
|
||||
not concern the majority of users running ZCPR3, NZ-COM, or Z3PLUS.
|
||||
|
||||
Patching is accomplished using ZCNFG and the configuration file,
|
||||
UNARCUnn.CFG, where nn is the current version. The options are discussed
|
||||
in detail in the CFG file help screens. ZCNFG will find the CFG file
|
||||
automatically, even if you change the name of the program, as long as you
|
||||
do not change the name of the CFG file.
|
||||
|
||||
PRINTING A FILE IN AN ARCHIVE
|
||||
-----------------------------
|
||||
For most users no configuration is necessary.
|
||||
|
||||
A single component file in an archive may be output directly to the printer
|
||||
(CP/M list device) by specifying a trailing "P" on the command line. The "P"
|
||||
must be the last command line character, and it must be separated from the
|
||||
second file parameter by a space. (The file parameter must specify a non-
|
||||
ambiguous file name and no disk drive name.) For example:
|
||||
ABOUT ARC/ARK FILES: The files which UNARCU processes utilize a format
|
||||
that was introduced by the ARC shareware utility program, which executes
|
||||
on 16-bit computers running the MS-DOS (or PC-DOS) operating system.
|
||||
This format has achieved widespread popularity since the ARC program
|
||||
first appeared in March 1985, and it has become the de facto standard for
|
||||
file storage on remote access systems catering to 16-bit computer users.
|
||||
This file format also achieved popularity on RCP/Ms (Remote CP/M) systems.
|
||||
While ARC files have given way to ZIP files in general, many ARC files are
|
||||
available on the web containing CP/M software.
|
||||
|
||||
A>UNARC CODES CHARLIE.TXT P
|
||||
RCP/M system operators adopted the convention of naming CP/M archive
|
||||
files with the filetype ARK. This differentiates these from MS-DOS archive
|
||||
files, which use the filetype ARC. This is a naming convention only; there
|
||||
is no difference in format, and UNARC will accept files of either type
|
||||
interchangeably.
|
||||
|
||||
The specified file is assumed to contain data suitable for printer output and
|
||||
is passed directly to the printer without alteration or additional formatting.
|
||||
This operation is particularly well-suited for output of binary graphics
|
||||
images on dot-matrix printers, since these can be extemely large but tend to
|
||||
compress quite well (e.g. to less than 5% of their original size). Note that
|
||||
the binary data filetypes which are excluded from typeout operations are also
|
||||
excluded from printing operations. Printing may be paused or aborted by use
|
||||
of the console CTRL-S and CTRL-C characters.
|
||||
An archive is a group of files compressed and collected together into a
|
||||
single file in such a way that the individual files may be recovered intact.
|
||||
In this respect, archives are similar in function to libraries (LBR files),
|
||||
which have been commonplace on CP/M systems since 1982, when the
|
||||
original LU library utility program was introduced by Gary P. Novosielski.
|
||||
The two file formats, however, are not compatible.)
|
||||
|
||||
The distinguishing characteristic of an ARC archive is that its component
|
||||
files are automatically compressed when they are added to the archive, so
|
||||
that the resulting file occupies a minimum amount of disk space. Of
|
||||
course, file compression techniques have also been commonplace in the CP/M
|
||||
world since 1981, when the public domain SQ and USQ "squeeze and
|
||||
unsqueeze" programs were introduced by Richard Greenlaw.
|
||||
|
||||
The SQ/USQ programs and their numerous popular descendants utilize a
|
||||
well-known general-purpose form of data compression (Huffman coding).
|
||||
This technique, which is also utilized in ARC files, performs well for many
|
||||
text files but often produces poor compression of binary files (e.g., object
|
||||
program COM files). The ARC program also provides an advanced data
|
||||
compression method, which it terms "crunching." This method (which is
|
||||
based on the Lempel-Ziv-Welch or "LZW" algorithm) performs better than
|
||||
squeezing in most cases, often achieving 50% or better compression of ASCII
|
||||
text files, 15-40% compression of binary object files, and as much as 95%
|
||||
compression of bit-mapped graphics image files.
|
||||
|
||||
CHECKING FILES IN AN ARCHIVE
|
||||
----------------------------
|
||||
Five different methods are actually employed for storing files in an
|
||||
archive. The method chosen for a particular file is the one which results
|
||||
in the best compression for that file:
|
||||
1. No compression ("unpacked"). The file is stored in its
|
||||
original form.
|
||||
2. Run-length encoding ("packed"). Repeated sequences of 3-
|
||||
255 identical bytes are compressed into a three-byte sequence.
|
||||
3. Huffman coding ("squeezed"). Each 8-bit byte (after run-
|
||||
length encoding) is encoded by a variable number of bits, with
|
||||
bit length (approximately) inversely proportional to the
|
||||
frequency of occurence of the corresponding byte.
|
||||
4. LZW compression ("crunched"). Variable-length strings
|
||||
of bytes (in theory, up to nearly 4000 bytes in length) are
|
||||
represented by a single (maximum) 12-bit code (after run-length
|
||||
encoding).
|
||||
5. LZW compression ("squashed"). This is a variation of
|
||||
crunching which uses (maximum) 13-bit codes (and no run-length
|
||||
encoding).
|
||||
|
||||
UNARC may be directed to extract one or more component files from an archive,
|
||||
without actually storing these as disk files, by specifying a trailing "C" on
|
||||
the command line. This operation performs file CRC and length checking, and
|
||||
it is useful for verifying correct modem data transmission of an archive. The
|
||||
"C" must be the last command line character, and it must be separated from the
|
||||
second file parameter by a space. (The file parameter must not specify a disk
|
||||
drive name, which indicates extraction to disk.) To check an entire archive,
|
||||
specify "*.*" for the second file parameter, for example:
|
||||
Since one of the five methods involves no compression at all, the resulting
|
||||
archive entry will never be larger than the original file.
|
||||
|
||||
A>UNARC CODES *.* C
|
||||
The last release of the MS-DOS ARC program (version 5.20) has eliminated
|
||||
squeezing as a compression technique. However, UNARC continues to
|
||||
process squeezed files for compatibility with archives created by earlier
|
||||
versions of ARC and by other MS-DOS archiving programs (notably PKARC).
|
||||
|
||||
The squashed compression method was introduced by the MS-DOS programs
|
||||
PKARC and PKXARC. UNARC can process files which use this method,
|
||||
although it is not universally accepted by other MS-DOS archive extraction
|
||||
programs (including ARC).
|
||||
|
||||
During its lifetime, the ARC program has undergone numerous revisions
|
||||
which have employed different variations on some of the above methods,
|
||||
particularly LZW compression. In order to retain compatibility with
|
||||
archives created by earlier program revisions, ARC stores a "version"
|
||||
indicator with each file in an archive. Based on this indicator, the latest
|
||||
release of the ARC program can always extract files created by older
|
||||
releases (although it will only use the latest data compression versions when
|
||||
adding new files to an archive).
|
||||
|
||||
PROGRAM OPTIONS
|
||||
---------------
|
||||
The current release of UNARC supports archive file versions generated by
|
||||
all releases of the following MS-DOS programs through (at least) the
|
||||
indicated program versions:
|
||||
ARC 5.20 (24 Oct 86), by System Enhancement Associates, Inc.
|
||||
ARCA 1.22 (13 Sep 86), by Wayne Chin and Vernon Buerg
|
||||
ARCH 5.38 (26 Jun 86), by Les Satenstein
|
||||
PKARC 2.0 (15 Dec 86), by Phil Katz (PKWARE, Inc.)
|
||||
UNARC does not recognize, but is unaffected by, the non-standard archive
|
||||
and file commenting feature of PKARC.
|
||||
|
||||
UNARC provides several options which may be used to tailor the program for
|
||||
specific non-universal requirements. Many of these are intended for RCP/M
|
||||
(Remote CP/M) system operators, to allow generation of a secure version of
|
||||
UNARC which can be used by remote callers for purposes of archive directory
|
||||
listing and/or file typeout only (but not file extraction). Others are
|
||||
provided for specialized non-standard CP/M systems and need not concern the
|
||||
majority of users running CP/M 2.2, CP/M 3.0 (CP/M Plus), or ZCPR3/ZRDOS
|
||||
systems. Additional options provide user preference features (such as the
|
||||
number of screen lines between console output pauses, or the list of filetypes
|
||||
excluded from typeout operations).
|
||||
Although the above discussion has emphasized the origin of archive files
|
||||
for the MS-DOS operating system, their use did spread to many other
|
||||
systems. Programs compatible with MS-DOS ARC have appeared for UNIX,
|
||||
Atari 68000, VAX/VMS, and TOPS-20 systems. A CP/M utility for building
|
||||
archive files is also available.
|
||||
|
||||
All of these options are described in UNARCOVL.ASM, an assembly language
|
||||
source file that can be edited and assembled to generate a HEX-format overlay
|
||||
for easy patching of the UNARC.COM or UNARCA.COM program files. Complete
|
||||
details are provided for technically-oriented users in UNARCOVL.ASM. However,
|
||||
the default options in the distributed program files are suitable for the
|
||||
majority of users with standard CP/M operating systems.
|
||||
|
||||
|
||||
|
||||
PROGRAM DISTRIBUTION
|
||||
--------------------
|
||||
|
||||
The UNARC program, its documentation, and all related files are distributed in
|
||||
archive file format (of course!). The distribution file is named UNARCxx.ARK,
|
||||
where "xx" is derived from the current version number (e.g. UNARC16.ARK for
|
||||
version 1.6). (This does not include the program source code, which is
|
||||
distributed separately.) This archive has the special characteristic that it
|
||||
is "self-unpacking." I.e., a separate copy of the UNARC.COM program file is
|
||||
NOT required to extract the component files from this archive.
|
||||
|
||||
The procedure for extracting the distribution files is quite simple: First,
|
||||
copy or rename UNARCxx.ARK to a program file, UNARCxx.COM, on the current disk
|
||||
drive. (Note that the filename, UNARCxx, must NOT be changed.) Then, run
|
||||
this program with a single optional command line parameter specifying the disk
|
||||
drive to which all distribution files will be extracted (defaults to current
|
||||
drive).
|
||||
|
||||
For example, assuming UNARC16.ARK is on drive B: and the files are to be
|
||||
extracted to drive C:, the following CP/M commands may be used:
|
||||
|
||||
A>B: ; Set current drive for UNARC16.ARK
|
||||
B>REN UNARC16.COM=UNARC16.ARK ; Rename it to UNARC16.COM
|
||||
B>UNARC16 C: ; Run it to extract all files to drive C:
|
||||
|
||||
Note that this self-unpacking capability is provided only by the distributed
|
||||
archive file, and it will not work if that file is altered or reconstructed.
|
||||
|
||||
|
||||
|
||||
AUTHOR'S NOTE
|
||||
-------------
|
||||
|
||||
I undertook writing the UNARC program to satisfy my curiosity about software
|
||||
developments in the MS-DOS/PC-DOS world. At the time I began work on UNARC,
|
||||
the MS-DOS ARC program had been in existence for over a year and had achieved
|
||||
widespread popularity and acceptance in the 16-bit community. Unfortunately,
|
||||
the lack of a compatible equivalent for CP/M systems rendered a large amount
|
||||
of public domain software inaccessible to 8-bit users such as myself. (Note
|
||||
that 16-bit software can indeed be of interest to users of 8-bit systems, e.g.
|
||||
Pascal and C language programs.)
|
||||
|
||||
Also, an increasing number of RCP/M systems now cater to both 8-bit and 16-bit
|
||||
users. Since the release of UNARC 1.0 (May 3, 1986), I have been encouraged
|
||||
to see that the program has found a welcome home on many such systems.
|
||||
Special thanks are due to Irv Hoff and Norman Beeler for providing archive
|
||||
file support in the KMD20 and LUX52 series of programs, respectively. With
|
||||
the increasing popularity of .ARC files on many different computer systems, I
|
||||
believe that continued such support of this compression format is both
|
||||
desirable and inevitable for CP/M systems. At the time of this writing I am
|
||||
about to release NOAH, a companion program to UNARC which will allow CP/M
|
||||
users to generate ARC-compatible files.
|
||||
|
||||
Bob Freed
|
||||
March 27, 1987
|
||||
|
||||
|
||||
|
||||
NOTICE
|
||||
|
||||
The UNARC program and its associated documentation is the copy-
|
||||
righted property of its author -- it is NOT in the public domain.
|
||||
HOWEVER... Free use, distribution, and modification of these
|
||||
files is permitted (and encouraged), subject to the following
|
||||
conditions:
|
||||
|
||||
(1) Such use or distribution must be for non-profit purposes only.
|
||||
(2) The author's copyright notice may not be altered or removed.
|
||||
(3) Modifications to this program or its documentation files may
|
||||
not be distributed without notification of and approval by
|
||||
the author.
|
||||
(4) The source program code may not be used, in whole or in part,
|
||||
in any other publicly-distributed or derivative work without
|
||||
similar notification and approval.
|
||||
|
||||
No fee is requested or expected for the use and distribution of
|
||||
this program subject to the above conditions. The author reserves
|
||||
the right to modify these conditions for any future revisions of
|
||||
this program. Questions, comments, suggestions, commercial
|
||||
inquiries, and bug reports or fixes are welcomed by the author:
|
||||
|
||||
Robert A. Freed
|
||||
62 Miller Road
|
||||
Newton Centre, MA 02159
|
||||
Telephone (617) 332-3533
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
For additional information about archive files and the MS-DOS ARC utility,
|
||||
refer to the documentation file, ARC.DOC, which is available on the web.
|
||||
For additional information about the LZW algorithm (and data compression
|
||||
methods in general), refer to the article "A Technique for High-Performance
|
||||
Data Compression", by Terry A. Welch, in IEEE Computer magazine, Vol. 17,
|
||||
No. 6, June 1984.
|
||||
|
||||
BIN
Source/Images/Common/Z/u14/UNARCU10.CFG
Normal file
BIN
Source/Images/Common/Z/u14/UNARCU10.CFG
Normal file
Binary file not shown.
@@ -1,42 +1,19 @@
|
||||
#
|
||||
# order is actually important, because of build dependencies
|
||||
#
|
||||
BUILDPROP := 1
|
||||
UNAME := $(shell uname)
|
||||
ifeq ($(UNAME), Linux)
|
||||
# Inhibit building Propeller on unsupported
|
||||
# Linux host architectures such as ARM eg. Raspberry Pi
|
||||
BUILDPROP := 0
|
||||
ARCH := $(shell uname -m)
|
||||
ifeq ($(ARCH), x86_64)
|
||||
BUILDPROP := 1
|
||||
endif
|
||||
ifeq ($(ARCH), i686)
|
||||
BUILDPROP := 1
|
||||
endif
|
||||
ifeq ($(ARCH), i386)
|
||||
BUILDPROP := 1
|
||||
endif
|
||||
ifeq ($(ARCH), x86)
|
||||
BUILDPROP := 1
|
||||
endif
|
||||
# Add here any more supported x86 based
|
||||
# uname machine strings for building Propeller
|
||||
endif
|
||||
|
||||
.PHONY: doc prop shared bp images rom zrc zzrcc
|
||||
.PHONY: doc prop shared bp images rom zrc z1rcc zzrcc
|
||||
|
||||
all: prop shared images rom zrc zzrcc
|
||||
.ONESHELL:
|
||||
.SHELLFLAGS = -cex
|
||||
|
||||
all: prop shared images rom zrc z1rcc zzrcc
|
||||
|
||||
doc:
|
||||
$(MAKE) --directory Doc $(ACTION)
|
||||
|
||||
prop:
|
||||
ifeq ($(BUILDPROP), 1)
|
||||
$(MAKE) --directory Prop $(ACTION)
|
||||
else
|
||||
$(info Builing Propeller is not supported on this $(ARCH) host Linux OS)
|
||||
endif
|
||||
|
||||
shared:
|
||||
$(MAKE) --directory HDIAG $(ACTION)
|
||||
@@ -67,14 +44,14 @@ rom:
|
||||
zrc:
|
||||
$(MAKE) --directory ZRC $(ACTION)
|
||||
|
||||
z1rcc:
|
||||
$(MAKE) --directory Z1RCC $(ACTION)
|
||||
|
||||
zzrcc:
|
||||
$(MAKE) --directory ZZRCC $(ACTION)
|
||||
|
||||
|
||||
clean: ACTION=clean
|
||||
|
||||
clean: all
|
||||
|
||||
diff: ACTION=diff
|
||||
|
||||
diff: all
|
||||
|
||||
@@ -3,17 +3,17 @@ setlocal
|
||||
|
||||
set TOOLS=../../Tools
|
||||
|
||||
set PATH=%TOOLS%\bst;%PATH%
|
||||
set PATH=%TOOLS%\OpenSpin;%PATH%
|
||||
|
||||
call :bstc PropIO
|
||||
call :bstc PropIO2
|
||||
call :bstc ParPortProp
|
||||
call :openspin PropIO
|
||||
call :openspin PropIO2
|
||||
call :openspin ParPortProp
|
||||
|
||||
goto :eof
|
||||
|
||||
:bstc
|
||||
:openspin
|
||||
echo.
|
||||
echo Building %1...
|
||||
bstc Spin\%1 -e -l || exit /b
|
||||
move /Y %1.eeprom "..\..\Binary" || exit /b
|
||||
openspin -e Spin\%1.spin || exit /b
|
||||
move /Y Spin\%1.eeprom "..\..\Binary" || exit /b
|
||||
goto :eof
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
@echo off
|
||||
setlocal
|
||||
|
||||
if exist *.eeprom del *.eeprom
|
||||
if exist *.list del *.list
|
||||
if exist Spin\*.eeprom del Spin\*.eeprom
|
||||
if exist Spin\*.list del Spin\*.list
|
||||
Binary file not shown.
Binary file not shown.
BIN
Source/RomDsk/RAM_1024KB/UNUARCU10.CFG
Normal file
BIN
Source/RomDsk/RAM_1024KB/UNUARCU10.CFG
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
Source/RomDsk/ROM_1024KB/UNUARCU10.CFG
Normal file
BIN
Source/RomDsk/ROM_1024KB/UNUARCU10.CFG
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
20
Source/Z1RCC/Bank Layout.txt
Normal file
20
Source/Z1RCC/Bank Layout.txt
Normal file
@@ -0,0 +1,20 @@
|
||||
Z1RCC has no real ROM. It has a single 512K RAM chip. The RomWBW
|
||||
ROMless startup mode is used.
|
||||
|
||||
The ROMless startup mode treats the entire 512KB as RAM. The entire
|
||||
512KB of RAM (less the top 32KB) must be preloaded by the Z1RCC CF
|
||||
Loader. There will be no ROM disk available under RomWBW. There will
|
||||
be a RAM Disk and it's initial contents will be seeded by the image
|
||||
loaded by the CF Loader.
|
||||
|
||||
Bank Contents Description
|
||||
-------- -------- -----------
|
||||
0x0 BIOS HBIOS Bank (operating)
|
||||
0x1 IMG0 ROM Loader, Monitor, ROM OSes
|
||||
0x2 IMG1 ROM Applications
|
||||
0x3 IMG2 Reserved
|
||||
0x4-0xB RAMD RAM Disk Banks
|
||||
0xC BUF OS Buffers (CP/M3)
|
||||
0xD AUX Aux Bank (CP/M 3, BPBIOS, etc.)
|
||||
0xE USR User Bank (CP/M TPA, etc.)
|
||||
0xF COM Common Bank, Upper 32KB
|
||||
23
Source/Z1RCC/Build.cmd
Normal file
23
Source/Z1RCC/Build.cmd
Normal file
@@ -0,0 +1,23 @@
|
||||
@echo off
|
||||
setlocal
|
||||
|
||||
set TOOLS=../../Tools
|
||||
|
||||
set PATH=%TOOLS%\srecord;%PATH%
|
||||
|
||||
if exist ..\..\Binary\RCZ180_z1rcc.rom call :build_z1rcc
|
||||
|
||||
goto :eof
|
||||
|
||||
:build_z1rcc
|
||||
|
||||
srec_cat -generate 0x0 0x100000 --constant 0x00 -o temp.dat -binary
|
||||
srec_cat temp.dat -binary -exclude 0x0 0x200 z1rcc_cfldr.bin -binary -o temp.dat -binary
|
||||
srec_cat temp.dat -binary -exclude 0x1B8 0x200 z1rcc_ptbl.bin -binary -offset 0x1B8 -o temp.dat -binary
|
||||
srec_cat temp.dat -binary -exclude 0x1F000 0x20000 z1rcc_mon.bin -binary -offset 0x1F000 -o temp.dat -binary
|
||||
srec_cat temp.dat -binary -exclude 0x24000 0xA4000 ..\..\Binary\RCZ180_z1rcc.rom -binary -offset 0x24000 -o temp.dat -binary
|
||||
move temp.dat ..\..\Binary\hd1k_z1rcc_prefix.dat
|
||||
|
||||
copy /b ..\..\Binary\hd1k_z1rcc_prefix.dat + ..\..\Binary\hd1k_cpm22.img + ..\..\Binary\hd1k_zsdos.img + ..\..\Binary\hd1k_nzcom.img + ..\..\Binary\hd1k_cpm3.img + ..\..\Binary\hd1k_zpm3.img + ..\..\Binary\hd1k_ws4.img ..\..\Binary\hd1k_z1rcc_combo.img || exit /b
|
||||
|
||||
goto :eof
|
||||
3
Source/Z1RCC/Clean.cmd
Normal file
3
Source/Z1RCC/Clean.cmd
Normal file
@@ -0,0 +1,3 @@
|
||||
@echo off
|
||||
setlocal
|
||||
|
||||
30
Source/Z1RCC/Makefile
Normal file
30
Source/Z1RCC/Makefile
Normal file
@@ -0,0 +1,30 @@
|
||||
HD1KZ1RCCPREFIX = hd1k_z1rcc_prefix.dat
|
||||
HD1KZ1RCCCOMBOIMG = hd1k_z1rcc_combo.img
|
||||
Z1RCCROM = ../../Binary/RCZ180_z1rcc.rom
|
||||
HD1KIMGS = ../../Binary/hd1k_cpm22.img ../../Binary/hd1k_zsdos.img ../../Binary/hd1k_nzcom.img \
|
||||
../../Binary/hd1k_cpm3.img ../../Binary/hd1k_zpm3.img ../../Binary/hd1k_ws4.img
|
||||
|
||||
OBJECTS :=
|
||||
|
||||
ifneq ($(wildcard $(Z1RCCROM)),)
|
||||
OBJECTS += $(HD1KZ1RCCPREFIX) $(HD1KZ1RCCCOMBOIMG)
|
||||
endif
|
||||
|
||||
DEST=../../Binary
|
||||
|
||||
TOOLS = ../../Tools
|
||||
|
||||
include $(TOOLS)/Makefile.inc
|
||||
|
||||
DIFFPATH = $(DIFFTO)/Binary
|
||||
|
||||
$(HD1KZ1RCCPREFIX):
|
||||
srec_cat -generate 0x0 0x100000 --constant 0x00 -o temp.dat -binary
|
||||
srec_cat temp.dat -binary -exclude 0x0 0x200 z1rcc_cfldr.bin -binary -o temp.dat -binary
|
||||
srec_cat temp.dat -binary -exclude 0x1B8 0x200 z1rcc_ptbl.bin -binary -offset 0x1B8 -o temp.dat -binary
|
||||
srec_cat temp.dat -binary -exclude 0x1F000 0x20000 z1rcc_mon.bin -binary -offset 0x1F000 -o temp.dat -binary
|
||||
srec_cat temp.dat -binary -exclude 0x24000 0xA4000 $(Z1RCCROM) -binary -offset 0x24000 -o temp.dat -binary
|
||||
mv temp.dat $@
|
||||
|
||||
$(HD1KZ1RCCCOMBOIMG): $(HD1KZ1RCCPREFIX) $(HD1KIMGS)
|
||||
cat $^ > $@
|
||||
24
Source/Z1RCC/Z1RCC Disk Layout.txt
Normal file
24
Source/Z1RCC/Z1RCC Disk Layout.txt
Normal file
@@ -0,0 +1,24 @@
|
||||
Z1RCC Disk Prefix Layout
|
||||
======================
|
||||
|
||||
---- Bytes ---- --- Sectors ---
|
||||
Start Length Start Length Description
|
||||
------- ------- ------- ------- ---------------------------
|
||||
0x00000 0x001BE 0 1 CF Boot Loader
|
||||
0x001B8 0x00048 RomWBW Partition Table
|
||||
0x00200 0x1EE00 1 247 Unused
|
||||
0x1F000 0x01000 248 8 Z1RCC Monitor v0.2a
|
||||
0x20000 0x04000 256 32 Unused
|
||||
0x24000 0x80000 288 1024 RomWBW
|
||||
0xA4000 0x5C000 1312 736 Unused
|
||||
0x100000 2048 Start of slices (partition 0x1E)
|
||||
|
||||
Notes
|
||||
-----
|
||||
|
||||
- At startup CPLD ROM is mapped to Z80 CPU address space 0x0000-0x003F, CPU begins execution at 0x0000
|
||||
- CPLD ROM (CF bootstrap mode) reads CF Boot Loader (512B) from start of CF (MBR) to 0xA000 and runs it
|
||||
- CF Boot Loader reads Z1RCC Monitor (4KB) from sectors 0xF8-0xFF of CF to 0xB000 and runs from 0xB400
|
||||
- Z1RCC Monitor reads 480KB (RomWBW) from sectors 0x120-0x4DF of CF into 480KB of physical RAM
|
||||
|
||||
|
||||
BIN
Source/Z1RCC/z1rcc_cfldr.bin
Normal file
BIN
Source/Z1RCC/z1rcc_cfldr.bin
Normal file
Binary file not shown.
BIN
Source/Z1RCC/z1rcc_mon.bin
Normal file
BIN
Source/Z1RCC/z1rcc_mon.bin
Normal file
Binary file not shown.
BIN
Source/Z1RCC/z1rcc_ptbl.bin
Normal file
BIN
Source/Z1RCC/z1rcc_ptbl.bin
Normal file
Binary file not shown.
@@ -14,8 +14,8 @@ goto :eof
|
||||
:build_zrc
|
||||
|
||||
srec_cat -generate 0x0 0x100000 --constant 0x00 -o temp.dat -binary
|
||||
srec_cat temp.dat -binary -exclude 0x0 0x100 zrc_cfldr.bin -binary -o temp.dat -binary
|
||||
srec_cat temp.dat -binary -exclude 0x100 0x200 zrc_ptbl.bin -binary -offset 0x100 -o temp.dat -binary
|
||||
srec_cat temp.dat -binary -exclude 0x0 0x200 zrc_cfldr.bin -binary -o temp.dat -binary
|
||||
srec_cat temp.dat -binary -exclude 0x1B8 0x200 zrc_ptbl.bin -binary -offset 0x1B8 -o temp.dat -binary
|
||||
srec_cat temp.dat -binary -exclude 0x1F000 0x20000 zrc_mon.bin -binary -offset 0x1F000 -o temp.dat -binary
|
||||
srec_cat temp.dat -binary -exclude 0x24000 0xA4000 ..\..\Binary\RCZ80_zrc.rom -binary -offset 0x24000 -o temp.dat -binary
|
||||
move temp.dat ..\..\Binary\hd1k_zrc_prefix.dat
|
||||
@@ -27,8 +27,8 @@ goto :eof
|
||||
:build_zrc_ram
|
||||
|
||||
srec_cat -generate 0x0 0x100000 --constant 0x00 -o temp.dat -binary
|
||||
srec_cat temp.dat -binary -exclude 0x0 0x100 zrc_cfldr.bin -binary -o temp.dat -binary
|
||||
srec_cat temp.dat -binary -exclude 0x100 0x200 zrc_ptbl.bin -binary -offset 0x100 -o temp.dat -binary
|
||||
srec_cat temp.dat -binary -exclude 0x0 0x200 zrc_cfldr.bin -binary -o temp.dat -binary
|
||||
srec_cat temp.dat -binary -exclude 0x1B8 0x200 zrc_ptbl.bin -binary -offset 0x1B8 -o temp.dat -binary
|
||||
srec_cat temp.dat -binary -exclude 0x1F000 0x20000 zrc_mon.bin -binary -offset 0x1F000 -o temp.dat -binary
|
||||
srec_cat temp.dat -binary -exclude 0x24000 0xA4000 ..\..\Binary\RCZ80_zrc_ram.rom -binary -offset 0x24000 -o temp.dat -binary
|
||||
move temp.dat ..\..\Binary\hd1k_zrc_ram_prefix.dat
|
||||
|
||||
@@ -27,16 +27,16 @@ DIFFPATH = $(DIFFTO)/Binary
|
||||
|
||||
$(HD1KZRCPREFIX):
|
||||
srec_cat -generate 0x0 0x100000 --constant 0x00 -o temp.dat -binary
|
||||
srec_cat temp.dat -binary -exclude 0x0 0x100 zrc_cfldr.bin -binary -o temp.dat -binary
|
||||
srec_cat temp.dat -binary -exclude 0x100 0x200 zrc_ptbl.bin -binary -offset 0x100 -o temp.dat -binary
|
||||
srec_cat temp.dat -binary -exclude 0x0 0x200 zrc_cfldr.bin -binary -o temp.dat -binary
|
||||
srec_cat temp.dat -binary -exclude 0x1B8 0x200 zrc_ptbl.bin -binary -offset 0x1B8 -o temp.dat -binary
|
||||
srec_cat temp.dat -binary -exclude 0x1F000 0x20000 zrc_mon.bin -binary -offset 0x1F000 -o temp.dat -binary
|
||||
srec_cat temp.dat -binary -exclude 0x24000 0xA4000 $(ZRCROM) -binary -offset 0x24000 -o temp.dat -binary
|
||||
mv temp.dat $@
|
||||
|
||||
$(HD1KZRCRAMPREFIX):
|
||||
srec_cat -generate 0x0 0x100000 --constant 0x00 -o temp.dat -binary
|
||||
srec_cat temp.dat -binary -exclude 0x0 0x100 zrc_cfldr.bin -binary -o temp.dat -binary
|
||||
srec_cat temp.dat -binary -exclude 0x100 0x200 zrc_ptbl.bin -binary -offset 0x100 -o temp.dat -binary
|
||||
srec_cat temp.dat -binary -exclude 0x0 0x200 zrc_cfldr.bin -binary -o temp.dat -binary
|
||||
srec_cat temp.dat -binary -exclude 0x1B8 0x200 zrc_ptbl.bin -binary -offset 0x1B8 -o temp.dat -binary
|
||||
srec_cat temp.dat -binary -exclude 0x1F000 0x20000 zrc_mon.bin -binary -offset 0x1F000 -o temp.dat -binary
|
||||
srec_cat temp.dat -binary -exclude 0x24000 0xA4000 $(ZRCRAMROM) -binary -offset 0x24000 -o temp.dat -binary
|
||||
mv temp.dat $@
|
||||
|
||||
@@ -4,8 +4,8 @@ ZRC Disk Prefix Layout
|
||||
---- Bytes ---- --- Sectors ---
|
||||
Start Length Start Length Description
|
||||
------- ------- ------- ------- ---------------------------
|
||||
0x00000 0x00100 0 0.5 CF Boot Loader
|
||||
0x00100 0x00100 0.5 0.5 RomWBW Partition Table
|
||||
0x00000 0x001BE 0 1 CF Boot Loader
|
||||
0x001B8 0x00048 RomWBW Partition Table
|
||||
0x00200 0x1EE00 1 247 Unused
|
||||
0x1F000 0x01000 248 8 ZRC Monitor v0.7
|
||||
0x20000 0x04000 256 32 Unused
|
||||
@@ -17,9 +17,9 @@ Notes
|
||||
-----
|
||||
|
||||
- At startup CPLD ROM is mapped to Z80 CPU address space 0x0000-0x003F, CPU begins execution at 0x0000
|
||||
- CPLD ROM (CF bootstrap mode) reads CF Boot Loader (256B) from start of CF (MBR) to 0xB000 and runs it
|
||||
- CPLD ROM (CF bootstrap mode) reads CF Boot Loader (512B) from start of CF (MBR) to 0xB000 and runs it
|
||||
- CF Boot Loader reads ZRC Monitor (4KB) from sectors 0xF8-0xFF of CF to 0xB400 and runs it
|
||||
- ZRC Monitor reads 512KB (RomWBW) from sectors 0x120-0x51F of CF into first 512KB of physical RAM
|
||||
- ZRC Monitor maps first 32KB of physical RAM to first 32KB of CPU RAM and starts execution at 0x0000
|
||||
|
||||
-- WBW 2:30 PM 10/8/2023
|
||||
-- WBW 3:30 PM 10/12/2023
|
||||
Binary file not shown.
Binary file not shown.
@@ -17,8 +17,8 @@ goto :eof
|
||||
:build_zzrcc
|
||||
|
||||
srec_cat -generate 0x0 0x100000 --constant 0x00 -o temp.dat -binary
|
||||
srec_cat temp.dat -binary -exclude 0x0 0x100 zzrcc_cfldr.bin -binary -o temp.dat -binary
|
||||
srec_cat temp.dat -binary -exclude 0x100 0x200 zzrcc_ptbl.bin -binary -offset 0x100 -o temp.dat -binary
|
||||
srec_cat temp.dat -binary -exclude 0x0 0x200 zzrcc_cfldr.bin -binary -o temp.dat -binary
|
||||
srec_cat temp.dat -binary -exclude 0x1B8 0x200 zzrcc_ptbl.bin -binary -offset 0x1B8 -o temp.dat -binary
|
||||
srec_cat temp.dat -binary -exclude 0x1F000 0x20000 zzrcc_mon.bin -binary -offset 0x1F000 -o temp.dat -binary
|
||||
srec_cat temp.dat -binary -exclude 0x24000 0xA4000 ..\..\Binary\RCZ280_zzrcc.rom -binary -offset 0x24000 -o temp.dat -binary
|
||||
move temp.dat ..\..\Binary\hd1k_zzrcc_prefix.dat
|
||||
@@ -30,8 +30,8 @@ goto :eof
|
||||
:build_zzrcc_ram
|
||||
|
||||
srec_cat -generate 0x0 0x100000 --constant 0x00 -o temp.dat -binary
|
||||
srec_cat temp.dat -binary -exclude 0x0 0x100 zzrcc_cfldr.bin -binary -o temp.dat -binary
|
||||
srec_cat temp.dat -binary -exclude 0x100 0x200 zzrcc_ptbl.bin -binary -offset 0x100 -o temp.dat -binary
|
||||
srec_cat temp.dat -binary -exclude 0x0 0x200 zzrcc_cfldr.bin -binary -o temp.dat -binary
|
||||
srec_cat temp.dat -binary -exclude 0x1B8 0x200 zzrcc_ptbl.bin -binary -offset 0x1B8 -o temp.dat -binary
|
||||
srec_cat temp.dat -binary -exclude 0x1F000 0x20000 zzrcc_mon.bin -binary -offset 0x1F000 -o temp.dat -binary
|
||||
srec_cat temp.dat -binary -exclude 0x24000 0xA4000 ..\..\Binary\RCZ280_zzrcc_ram.rom -binary -offset 0x24000 -o temp.dat -binary
|
||||
move temp.dat ..\..\Binary\hd1k_zzrcc_ram_prefix.dat
|
||||
|
||||
@@ -27,16 +27,16 @@ DIFFPATH = $(DIFFTO)/Binary
|
||||
|
||||
$(HD1KZZRCCPREFIX):
|
||||
srec_cat -generate 0x0 0x100000 --constant 0x00 -o temp.dat -binary
|
||||
srec_cat temp.dat -binary -exclude 0x0 0x100 zzrcc_cfldr.bin -binary -o temp.dat -binary
|
||||
srec_cat temp.dat -binary -exclude 0x100 0x200 zzrcc_ptbl.bin -binary -offset 0x100 -o temp.dat -binary
|
||||
srec_cat temp.dat -binary -exclude 0x0 0x200 zzrcc_cfldr.bin -binary -o temp.dat -binary
|
||||
srec_cat temp.dat -binary -exclude 0x1B8 0x200 zzrcc_ptbl.bin -binary -offset 0x1B8 -o temp.dat -binary
|
||||
srec_cat temp.dat -binary -exclude 0x1F000 0x20000 zzrcc_mon.bin -binary -offset 0x1F000 -o temp.dat -binary
|
||||
srec_cat temp.dat -binary -exclude 0x24000 0xA4000 $(ZZRCCROM) -binary -offset 0x24000 -o temp.dat -binary
|
||||
mv temp.dat $@
|
||||
|
||||
$(HD1KZZRCCRAMPREFIX):
|
||||
srec_cat -generate 0x0 0x100000 --constant 0x00 -o temp.dat -binary
|
||||
srec_cat temp.dat -binary -exclude 0x0 0x100 zzrcc_cfldr.bin -binary -o temp.dat -binary
|
||||
srec_cat temp.dat -binary -exclude 0x100 0x200 zzrcc_ptbl.bin -binary -offset 0x100 -o temp.dat -binary
|
||||
srec_cat temp.dat -binary -exclude 0x0 0x200 zzrcc_cfldr.bin -binary -o temp.dat -binary
|
||||
srec_cat temp.dat -binary -exclude 0x1B8 0x200 zzrcc_ptbl.bin -binary -offset 0x1B8 -o temp.dat -binary
|
||||
srec_cat temp.dat -binary -exclude 0x1F000 0x20000 zzrcc_mon.bin -binary -offset 0x1F000 -o temp.dat -binary
|
||||
srec_cat temp.dat -binary -exclude 0x24000 0xA4000 $(ZZRCCRAMROM) -binary -offset 0x24000 -o temp.dat -binary
|
||||
mv temp.dat $@
|
||||
|
||||
@@ -4,8 +4,8 @@ ZZRCC Disk Prefix Layout
|
||||
---- Bytes ---- --- Sectors ---
|
||||
Start Length Start Length Description
|
||||
------- ------- ------- ------- ---------------------------
|
||||
0x00000 0x00100 0 0.5 CF Boot Loader
|
||||
0x00100 0x00100 0.5 0.5 RomWBW Partition Table
|
||||
0x00000 0x001BE 0 1 CF Boot Loader
|
||||
0x001B8 0x00048 RomWBW Partition Table
|
||||
0x00200 0x1EE00 1 247 Unused
|
||||
0x1F000 0x01000 248 8 ZZRCC Monitor v0.5
|
||||
0x20000 0x04000 256 32 Unused
|
||||
@@ -17,9 +17,9 @@ Notes
|
||||
-----
|
||||
|
||||
- At startup CPLD ROM is mapped to Z280 CPU address space 0x0000-0x003F, CPU begins execution at 0x0000
|
||||
- CPLD ROM (CF bootstrap mode) reads CF Boot Loader (256B) from start of CF (MBR) to 0xB000 and runs it
|
||||
- CPLD ROM (CF bootstrap mode) reads CF Boot Loader (512B) from start of CF (MBR) to 0xB000 and runs it
|
||||
- CF Boot Loader reads ZZRCC Monitor (4KB) from sectors 0xF8-0xFF of CF to 0xB400 and runs it
|
||||
- ZZRCC Monitor reads 512KB (RomWBW) from sectors 0x120-0x51F of CF into first 512KB of physical RAM
|
||||
- ZZRCC Monitor maps first 32KB of physical RAM to first 32KB of CPU RAM and starts execution at 0x0000
|
||||
|
||||
-WBW 2:36 PM 10/8/2023
|
||||
-WBW 3:30 PM 10/12/2023
|
||||
Binary file not shown.
Binary file not shown.
@@ -2,7 +2,7 @@
|
||||
#DEFINE RMN 4
|
||||
#DEFINE RUP 0
|
||||
#DEFINE RTP 0
|
||||
#DEFINE BIOSVER "3.4.0-dev.7"
|
||||
#DEFINE BIOSVER "3.4.0-dev.23"
|
||||
#define rmj RMJ
|
||||
#define rmn RMN
|
||||
#define rup RUP
|
||||
|
||||
@@ -3,5 +3,5 @@ rmn equ 4
|
||||
rup equ 0
|
||||
rtp equ 0
|
||||
biosver macro
|
||||
db "3.4.0-dev.7"
|
||||
db "3.4.0-dev.23"
|
||||
endm
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
#
|
||||
# build the tools for linux and Darwin
|
||||
#
|
||||
|
||||
.ONESHELL:
|
||||
.SHELLFLAGS = -cex
|
||||
|
||||
UNAME := $(shell uname)
|
||||
|
||||
all:
|
||||
|
||||
@@ -42,7 +42,6 @@ export CPMDIR80=$(TOOLS)/cpm/
|
||||
TASM=$(BINDIR)/uz80as -t z80
|
||||
TASMFLAGS=
|
||||
OPENSPIN=$(BINDIR)/openspin
|
||||
BSTC=$(BINDIR)//bstc
|
||||
CPMCP=$(BINDIR)/cpmcp
|
||||
CPMCHATTR=$(BINDIR)/cpmchattr
|
||||
|
||||
@@ -115,19 +114,8 @@ CPM=$(TOOLS)/cpm/bin80/
|
||||
%.com: %.rel
|
||||
$(ZXCC) $(CPM)/L80 -$(basename $<),$(basename $<).com/n/e
|
||||
|
||||
ifeq ($(UNAME), Linux)
|
||||
%.eeprom: %.spin
|
||||
$(BSTC) -e -l $<
|
||||
endif
|
||||
|
||||
#
|
||||
# darwin bstc won't run, since mac os does not do 32 bit binaries any more
|
||||
# openspin ought to work
|
||||
#
|
||||
ifeq ($(UNAME), Darwin)
|
||||
%.eeprom: %.spin
|
||||
$(OPENSPIN) -e $<
|
||||
endif
|
||||
|
||||
#
|
||||
# first target is default
|
||||
|
||||
BIN
Tools/OpenSpin/openspin.exe
Normal file
BIN
Tools/OpenSpin/openspin.exe
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1,6 +1,10 @@
|
||||
#
|
||||
# build the tools for linux and Darwin
|
||||
#
|
||||
|
||||
.ONESHELL:
|
||||
.SHELLFLAGS = -cex
|
||||
|
||||
UNAME := $(shell uname)
|
||||
ifeq ($(UNAME), Linux)
|
||||
SUFFIX=linux
|
||||
@@ -9,7 +13,7 @@ ifeq ($(UNAME), Darwin)
|
||||
SUFFIX=osx
|
||||
endif
|
||||
|
||||
SUBDIRS = bst uz80as zxcc cpmtools bin2asm lzsa
|
||||
SUBDIRS = OpenSpin uz80as zxcc cpmtools bin2asm lzsa
|
||||
|
||||
all:
|
||||
@chmod +x casefn.sh
|
||||
|
||||
5
Tools/unix/OpenSpin/.travis.yml
Normal file
5
Tools/unix/OpenSpin/.travis.yml
Normal file
@@ -0,0 +1,5 @@
|
||||
language: c
|
||||
os:
|
||||
- linux
|
||||
- osx
|
||||
script: make
|
||||
68
Tools/unix/OpenSpin/Makefile
Normal file
68
Tools/unix/OpenSpin/Makefile
Normal file
@@ -0,0 +1,68 @@
|
||||
# modified for RomWBW build environment
|
||||
|
||||
UNAME := $(shell uname)
|
||||
DEST = ../../$(UNAME)
|
||||
|
||||
# cross compilation scheme taken from Eric Smith's spin2cpp compiler
|
||||
# if CROSS is defined, we are building a cross compiler
|
||||
# possible targets are: win32, rpi
|
||||
|
||||
ifeq ($(CC),)
|
||||
CC=gcc
|
||||
endif
|
||||
|
||||
ifeq ($(CXX),)
|
||||
CXX=g++
|
||||
endif
|
||||
|
||||
ifeq ($(CROSS),win32)
|
||||
CC=i686-w64-mingw32-gcc
|
||||
CXX=i686-w64-mingw32-g++
|
||||
EXT=.exe
|
||||
BUILD=./build-win32
|
||||
else ifeq ($(CROSS),rpi)
|
||||
CC=arm-linux-gnueabihf-gcc
|
||||
CXX=arm-linux-gnueabihf-g++
|
||||
EXT=
|
||||
BUILD=./build-rpi
|
||||
else
|
||||
EXT=
|
||||
BUILD=./build
|
||||
endif
|
||||
|
||||
OS:=$(shell uname)
|
||||
|
||||
ifeq ($(OS),Darwin)
|
||||
CFLAGS+=-Wall -g -Wno-self-assign
|
||||
else
|
||||
CFLAGS+=-Wall -g $(MSTATIC)
|
||||
endif
|
||||
|
||||
CXXFLAGS += $(CFLAGS)
|
||||
|
||||
TARGET=$(BUILD)/openspin$(EXT)
|
||||
SRCDIR=SpinSource
|
||||
OBJ=$(BUILD)/openspin.o \
|
||||
$(BUILD)/pathentry.o
|
||||
|
||||
LIBNAME=$(BUILD)/PropellerCompiler/libopenspin.a
|
||||
|
||||
all: $(BUILD) $(DEST) $(LIBNAME) $(OBJ) Makefile
|
||||
$(CXX) -o $(TARGET) $(CXXFLAGS) $(OBJ) $(LIBNAME)
|
||||
cp -p $(TARGET) $(DEST)
|
||||
|
||||
$(BUILD)/%.o: $(SRCDIR)/%.cpp
|
||||
$(CXX) $(CXXFLAGS) -o $@ -c $<
|
||||
|
||||
$(LIBNAME): $(BUILD)
|
||||
$(MAKE) -C PropellerCompiler CROSS=$(CROSS) BUILD=$(realpath $(BUILD))/PropellerCompiler all
|
||||
|
||||
$(BUILD):
|
||||
mkdir -p $(BUILD)
|
||||
|
||||
$(DEST):
|
||||
mkdir -p $(DEST)
|
||||
|
||||
clean:
|
||||
rm -rf $(BUILD)
|
||||
make -C PropellerCompiler BUILD=$(realpath $(BUILD))/PropellerCompiler clean
|
||||
136
Tools/unix/OpenSpin/PropellerCompiler/BlockNestStackRoutines.cpp
Normal file
136
Tools/unix/OpenSpin/PropellerCompiler/BlockNestStackRoutines.cpp
Normal file
@@ -0,0 +1,136 @@
|
||||
//////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// Propeller Spin/PASM Compiler //
|
||||
// (c)2012-2016 Parallax Inc. DBA Parallax Semiconductor. //
|
||||
// Adapted from Chip Gracey's x86 asm code by Roy Eltham //
|
||||
// See end of file for terms of use. //
|
||||
// //
|
||||
//////////////////////////////////////////////////////////////
|
||||
//
|
||||
// BlockNestStackRoutines.cpp
|
||||
//
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
#include "Utilities.h"
|
||||
#include "PropellerCompilerInternal.h"
|
||||
#include "SymbolEngine.h"
|
||||
#include "Elementizer.h"
|
||||
#include "ErrorStrings.h"
|
||||
#include "CompileUtilities.h"
|
||||
|
||||
//
|
||||
// Block Nest Routines
|
||||
//
|
||||
|
||||
bool BlockNest_New(unsigned char type, int stackSize)
|
||||
{
|
||||
if (g_pCompilerData->bnest_ptr > block_nest_limit)
|
||||
{
|
||||
g_pCompilerData->error = true;
|
||||
g_pCompilerData->error_msg = g_pErrorStrings[error_loxnbe];
|
||||
return false;
|
||||
}
|
||||
|
||||
// set blockstack base
|
||||
g_pCompilerData->bnest_type[g_pCompilerData->bnest_ptr] = type;
|
||||
g_pCompilerData->bstack_base[g_pCompilerData->bnest_ptr++] = g_pCompilerData->bstack_ptr;
|
||||
|
||||
// init bstack values to max forward
|
||||
for (int i = 0; i < stackSize; i++)
|
||||
{
|
||||
g_pCompilerData->bstack[g_pCompilerData->bstack_ptr + i] = 0x0000FFC0;
|
||||
}
|
||||
g_pCompilerData->bstack_ptr += stackSize;
|
||||
if (g_pCompilerData->bstack_ptr >= block_stack_limit)
|
||||
{
|
||||
g_pCompilerData->error = true;
|
||||
g_pCompilerData->error_msg = g_pErrorStrings[error_bnso];
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void BlockNest_Redo(unsigned char type)
|
||||
{
|
||||
g_pCompilerData->bnest_type[g_pCompilerData->bnest_ptr - 1] = type;
|
||||
}
|
||||
|
||||
void BlockNest_End()
|
||||
{
|
||||
g_pCompilerData->bnest_ptr--;
|
||||
g_pCompilerData->bstack_ptr = g_pCompilerData->bstack_base[g_pCompilerData->bnest_ptr];
|
||||
}
|
||||
|
||||
//
|
||||
// Block Stack Routines
|
||||
//
|
||||
|
||||
void BlockStack_Write(int address, int value)
|
||||
{
|
||||
int stackAddress = g_pCompilerData->bstack_base[g_pCompilerData->bnest_ptr - 1] + address;
|
||||
g_pCompilerData->bstack[stackAddress] = value;
|
||||
}
|
||||
|
||||
int BlockStack_Read(int address)
|
||||
{
|
||||
int stackAddress = g_pCompilerData->bstack_base[g_pCompilerData->bnest_ptr - 1] + address;
|
||||
return g_pCompilerData->bstack[stackAddress];
|
||||
}
|
||||
|
||||
bool BlockStack_CompileAddress(int address)
|
||||
{
|
||||
return CompileAddress(BlockStack_Read(address));
|
||||
}
|
||||
|
||||
bool BlockStack_CompileConstant()
|
||||
{
|
||||
int value = BlockStack_Read(0);
|
||||
|
||||
if (value >= 0x100)
|
||||
{
|
||||
// two byte
|
||||
if (!EnterObj(0x39)) // 0x39 = 00111001b
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (!EnterObj((unsigned char)((value >> 8) & 0xFF)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// one byte
|
||||
if (!EnterObj(0x38)) // 0x38 = 00111000b
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return EnterObj((unsigned char)(value & 0xFF));
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// TERMS OF USE: MIT License //
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy of this //
|
||||
// software and associated documentation files (the "Software"), to deal in the Software //
|
||||
// without restriction, including without limitation the rights to use, copy, modify, //
|
||||
// merge, publish, distribute, sublicense, and/or sell copies of the Software, and to //
|
||||
// permit persons to whom the Software is furnished to do so, subject to the following //
|
||||
// conditions: //
|
||||
// //
|
||||
// The above copyright notice and this permission notice shall be included in all copies //
|
||||
// or substantial portions of the Software. //
|
||||
// //
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, //
|
||||
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A //
|
||||
// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT //
|
||||
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION //
|
||||
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE //
|
||||
// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. //
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
932
Tools/unix/OpenSpin/PropellerCompiler/CompileDatBlocks.cpp
Normal file
932
Tools/unix/OpenSpin/PropellerCompiler/CompileDatBlocks.cpp
Normal file
@@ -0,0 +1,932 @@
|
||||
//////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// Propeller Spin/PASM Compiler //
|
||||
// (c)2012-2016 Parallax Inc. DBA Parallax Semiconductor. //
|
||||
// Adapted from Chip Gracey's x86 asm code by Roy Eltham //
|
||||
// See end of file for terms of use. //
|
||||
// //
|
||||
//////////////////////////////////////////////////////////////
|
||||
//
|
||||
// CompileDatBlocks.cpp
|
||||
//
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
#include "Utilities.h"
|
||||
#include "PropellerCompilerInternal.h"
|
||||
#include "SymbolEngine.h"
|
||||
#include "Elementizer.h"
|
||||
#include "ErrorStrings.h"
|
||||
|
||||
void CompileDatBlocks_EnterInfo(int datstart, int objstart)
|
||||
{
|
||||
g_pCompilerData->inf_start = datstart;
|
||||
g_pCompilerData->inf_finish = g_pElementizer->GetSourcePtr();
|
||||
g_pCompilerData->inf_data0 = objstart;
|
||||
g_pCompilerData->inf_data1 = g_pCompilerData->obj_ptr;
|
||||
g_pCompilerData->inf_data2 = 0;
|
||||
g_pCompilerData->inf_data3 = 0;
|
||||
g_pCompilerData->inf_data4 = 0;
|
||||
g_pCompilerData->inf_type = info_dat;
|
||||
EnterInfo();
|
||||
}
|
||||
|
||||
void CompileDatBlocks_EnterSymbol(bool bResSymbol, int size)
|
||||
{
|
||||
int value_1 = g_pCompilerData->obj_ptr;
|
||||
int value_2 = g_pCompilerData->cog_org;
|
||||
g_pCompilerData->inf_data0 = value_1;
|
||||
g_pCompilerData->inf_data1 = size;
|
||||
g_pCompilerData->inf_data2 = value_2;
|
||||
g_pCompilerData->inf_data3 = 0;
|
||||
g_pCompilerData->inf_data4 = 0;
|
||||
g_pCompilerData->inf_type = info_dat_symbol;
|
||||
EnterInfo();
|
||||
g_pSymbolEngine->AddSymbol(g_pCompilerData->symbolBackup, bResSymbol ? type_dat_long_res : (size == 0 ? type_dat_byte : (size == 1 ? type_dat_word : type_dat_long)), value_1, value_2);
|
||||
#ifdef RPE_DEBUG
|
||||
printf("dat: %s %08X %08X (%d)\n", g_pCompilerData->symbolBackup, value_1, value_2, size);
|
||||
#endif
|
||||
}
|
||||
|
||||
bool CompileDatBlocks_EnterByte(unsigned char value)
|
||||
{
|
||||
if (EnterObj(value))
|
||||
{
|
||||
if (g_pCompilerData->orgx == 0)
|
||||
{
|
||||
g_pCompilerData->cog_org++;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CompileDatBlocks_Enter(int value, int count, int size)
|
||||
{
|
||||
int numBytesPer = 1 << size;
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
if(!CompileDatBlocks_EnterByte(value & 0x000000FF))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (numBytesPer > 1)
|
||||
{
|
||||
if(!CompileDatBlocks_EnterByte((value >> 8) & 0x000000FF))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (numBytesPer > 2)
|
||||
{
|
||||
if(!CompileDatBlocks_EnterByte((value >> 16) & 0x000000FF))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if(!CompileDatBlocks_EnterByte((value >> 24) & 0x000000FF))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CompileDatBlocks_Advance(bool bSymbol, bool bResSymbol, int size)
|
||||
{
|
||||
int testVal = (1 << size) - 1;
|
||||
for (;;)
|
||||
{
|
||||
if ((g_pCompilerData->obj_ptr & testVal) == 0)
|
||||
{
|
||||
if (bSymbol)
|
||||
{
|
||||
CompileDatBlocks_EnterSymbol(bResSymbol, size);
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (!CompileDatBlocks_EnterByte(0)) // obj_ptr gets incremented in here
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CompileDatBlocks_Data(bool& bEof, int pass, bool bSymbol, bool& bResSymbol, int& size)
|
||||
{
|
||||
size = g_pElementizer->GetValue() & 0x000000FF;
|
||||
int overrideSize = size;
|
||||
|
||||
if (!CompileDatBlocks_Advance(bSymbol, bResSymbol, size))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!g_pElementizer->GetNext(bEof))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (g_pElementizer->GetType() == type_end)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
while (!bEof)
|
||||
{
|
||||
// do we have a size override?
|
||||
if (g_pElementizer->GetType() == type_size)
|
||||
{
|
||||
// yes, get it
|
||||
overrideSize = g_pElementizer->GetValue() & 0x000000FF;
|
||||
if (overrideSize < size)
|
||||
{
|
||||
g_pCompilerData->error = true;
|
||||
g_pCompilerData->error_msg = g_pErrorStrings[error_sombl];
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// no, backup
|
||||
g_pElementizer->Backup();
|
||||
}
|
||||
|
||||
// get the value
|
||||
if (!GetTryValue(pass == 1 ? true : false, overrideSize == 2 ? false : true, true))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
int value = GetResult();
|
||||
|
||||
// get the count
|
||||
int count = 1;
|
||||
if (g_pElementizer->CheckElement(type_leftb))
|
||||
{
|
||||
if (!GetTryValue(true, true, true))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
count = GetResult();
|
||||
if (!g_pElementizer->GetElement(type_rightb))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// enter the value count times into the obj
|
||||
if (!CompileDatBlocks_Enter(value, count, overrideSize))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool bComma = false;
|
||||
if (!GetCommaOrEnd(bComma))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (!bComma)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if (!g_pElementizer->GetNext(bEof))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CompileDatBlocks_File(bool bSymbol, bool bResSymbol, int& size)
|
||||
{
|
||||
size = 0; // force size to byte
|
||||
if (bSymbol)
|
||||
{
|
||||
CompileDatBlocks_EnterSymbol(bResSymbol, size);
|
||||
}
|
||||
|
||||
int filenameStart = 0;
|
||||
int filenameFinish = 0;
|
||||
if (!GetFilename(filenameStart, filenameFinish))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// find the file in the dat_data array and copy it into obj
|
||||
for (int i = 0; i < g_pCompilerData->dat_files; i++)
|
||||
{
|
||||
if (strcmp(&(g_pCompilerData->dat_filenames[256*i]), g_pCompilerData->filename) == 0)
|
||||
{
|
||||
// copy dat data into obj (RPE: this should be optimized)
|
||||
for (int j = 0; j < g_pCompilerData->dat_lengths[i]; j++)
|
||||
{
|
||||
if (!CompileDatBlocks_EnterByte(g_pCompilerData->dat_data[g_pCompilerData->dat_offsets[i] + j]))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (!g_pElementizer->GetElement(type_end))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// file data not found
|
||||
g_pCompilerData->error = true;
|
||||
g_pCompilerData->error_msg = g_pErrorStrings[error_idfnf];
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CompileDatBlocks_AsmDirective(bool bSymbol, bool& bResSymbol, int& size)
|
||||
{
|
||||
size = 2; // force to long size
|
||||
|
||||
int directive = g_pElementizer->GetValue() & 0x000000FF;
|
||||
switch (directive)
|
||||
{
|
||||
case dir_nop:
|
||||
{
|
||||
if (!CompileDatBlocks_Advance(bSymbol, bResSymbol, size))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (!g_pElementizer->GetElement(type_end))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (!CompileDatBlocks_Enter(0, 1, 2)) // enter a 0 long
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
case dir_fit:
|
||||
{
|
||||
if (!CompileDatBlocks_Advance(bSymbol, bResSymbol, size))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
int fit = 0x1F0;
|
||||
if (!g_pElementizer->CheckElement(type_end))
|
||||
{
|
||||
if (!GetTryValue(true, true, true))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
fit = GetResult();
|
||||
if (!g_pElementizer->GetElement(type_end))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
fit <<= 2;
|
||||
if ((unsigned int)(g_pCompilerData->cog_org) > (unsigned int)fit)
|
||||
{
|
||||
g_pCompilerData->error = true;
|
||||
g_pCompilerData->error_msg = g_pErrorStrings[error_oefl];
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
case dir_res:
|
||||
{
|
||||
if (g_pCompilerData->orgx != 0)
|
||||
{
|
||||
g_pCompilerData->error = true;
|
||||
g_pCompilerData->error_msg = g_pErrorStrings[error_rinaiom];
|
||||
return false;
|
||||
}
|
||||
bResSymbol = true;
|
||||
if (!CompileDatBlocks_Advance(bSymbol, bResSymbol, size))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
int resSize = 1;
|
||||
if (!g_pElementizer->CheckElement(type_end))
|
||||
{
|
||||
if (!GetTryValue(true, true, true))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
resSize = GetResult();
|
||||
if (!g_pElementizer->GetElement(type_end))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
resSize <<= 2;
|
||||
g_pCompilerData->cog_org += resSize;
|
||||
if (g_pCompilerData->cog_org > (0x1F0 * 4))
|
||||
{
|
||||
g_pCompilerData->error = true;
|
||||
g_pCompilerData->error_msg = g_pErrorStrings[error_oexl];
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
case dir_org:
|
||||
{
|
||||
if (!CompileDatBlocks_Advance(bSymbol, bResSymbol, size))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
int newOrg = 0;
|
||||
if (!g_pElementizer->CheckElement(type_end))
|
||||
{
|
||||
if (!GetTryValue(true, true, true))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
newOrg = GetResult();
|
||||
if (!g_pElementizer->GetElement(type_end))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (newOrg > 0x1F0)
|
||||
{
|
||||
g_pCompilerData->error = true;
|
||||
g_pCompilerData->error_msg = g_pErrorStrings[error_oexl];
|
||||
return false;
|
||||
}
|
||||
g_pCompilerData->cog_org = newOrg << 2;
|
||||
g_pCompilerData->orgx = 0;
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (!CompileDatBlocks_Advance(bSymbol, bResSymbol, size))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (!g_pElementizer->GetElement(type_end))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
g_pCompilerData->cog_org = 0;
|
||||
g_pCompilerData->orgx = 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CompileDatBlocks_ValidateCallSymbol(bool bIsRet, char* pSymbol)
|
||||
{
|
||||
if (!g_pElementizer->FindSymbol(pSymbol))
|
||||
{
|
||||
g_pCompilerData->error = true;
|
||||
g_pCompilerData->error_msg = g_pErrorStrings[error_eads];
|
||||
return false;
|
||||
}
|
||||
if (g_pElementizer->GetType() == type_undefined)
|
||||
{
|
||||
g_pCompilerData->error = true;
|
||||
g_pCompilerData->error_msg = g_pErrorStrings[bIsRet ? error_urs : error_us];
|
||||
return false;
|
||||
}
|
||||
if (g_pElementizer->GetType() < type_dat_byte || g_pElementizer->GetType() > type_dat_long_res)
|
||||
{
|
||||
g_pCompilerData->error = true;
|
||||
g_pCompilerData->error_msg = g_pErrorStrings[error_eads];
|
||||
return false;
|
||||
}
|
||||
|
||||
// the offset to the label symbol is in second symbol value
|
||||
int value = g_pElementizer->GetValue2();
|
||||
|
||||
// make sure it's long aligned
|
||||
if (value & 0x03)
|
||||
{
|
||||
g_pCompilerData->error = true;
|
||||
g_pCompilerData->error_msg = g_pErrorStrings[bIsRet ? error_rainl : error_ainl];
|
||||
return false;
|
||||
}
|
||||
// make sure is in range
|
||||
value >>= 2;
|
||||
if (value >= 0x1F0)
|
||||
{
|
||||
g_pCompilerData->error = true;
|
||||
g_pCompilerData->error_msg = g_pErrorStrings[bIsRet ? error_raioor : error_aioor];
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CompileDatBlocks_AsmInstruction(bool& bEof, int pass, bool bSymbol, bool bResSymbol, int& size, unsigned char condition)
|
||||
{
|
||||
size = 2; // force to long size
|
||||
if (!CompileDatBlocks_Advance(bSymbol, bResSymbol, size))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
int opcode = g_pElementizer->GetValue() & 0x000000FF;
|
||||
// handle dual type entries and also AND and OR (which are the only type_binary that will get here)
|
||||
if (g_pElementizer->IsDual() || g_pElementizer->GetType() == type_binary)
|
||||
{
|
||||
opcode = g_pElementizer->GetAsm() & 0x000000FF;
|
||||
}
|
||||
|
||||
unsigned int instruction = opcode << 8;
|
||||
|
||||
if (opcode & 0x80) // sys instruction
|
||||
{
|
||||
instruction = 0x03 << 8;
|
||||
}
|
||||
|
||||
instruction |= condition;
|
||||
|
||||
if (opcode & 0x40) // set WR?
|
||||
{
|
||||
instruction |= 0x20;
|
||||
}
|
||||
|
||||
instruction <<= 18; // justify the instruction (s & d will go in lower 18 bits)
|
||||
|
||||
if (opcode & 0x80) // sys instruction
|
||||
{
|
||||
instruction |= 0x00400000; // set immediate
|
||||
instruction |= (opcode & 0x07); // set s
|
||||
|
||||
// get d
|
||||
if (!GetTryValue(pass == 1 ? true : false, true, true))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
int d = GetResult();
|
||||
if (d > 0x1FF)
|
||||
{
|
||||
g_pCompilerData->error = true;
|
||||
g_pCompilerData->error_msg = g_pErrorStrings[error_drcex];
|
||||
return false;
|
||||
}
|
||||
instruction |= (d << 9); // set d
|
||||
}
|
||||
else if (opcode == 0x15) // call?
|
||||
{
|
||||
// make 'jmpret label_ret, #label'
|
||||
instruction ^= 0x08C00000;
|
||||
if (!g_pElementizer->GetElement(type_pound))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
int length = 0;
|
||||
if (!GetSymbol(&length))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (length > 0)
|
||||
{
|
||||
if (length > symbol_limit - 4)
|
||||
{
|
||||
g_pCompilerData->error = true;
|
||||
g_pCompilerData->error_msg = g_pErrorStrings[error_csmnexc];
|
||||
return false;
|
||||
}
|
||||
char* pSymbol = g_pElementizer->GetCurrentSymbol();
|
||||
if (pass == 1)
|
||||
{
|
||||
if (!CompileDatBlocks_ValidateCallSymbol(false, pSymbol))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
instruction |= ((g_pElementizer->GetValue2() & 0x7FF) >> 2); // set #label
|
||||
|
||||
pSymbol[length] = '_';
|
||||
pSymbol[length+1] = 'R';
|
||||
pSymbol[length+2] = 'E';
|
||||
pSymbol[length+3] = 'T';
|
||||
pSymbol[length+4] = 0;
|
||||
if (pass == 1)
|
||||
{
|
||||
if (!CompileDatBlocks_ValidateCallSymbol(true, pSymbol))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
instruction |= (((g_pElementizer->GetValue2() & 0x7FF) >> 2) << 9); // set label_ret
|
||||
}
|
||||
else
|
||||
{
|
||||
g_pCompilerData->error = true;
|
||||
g_pCompilerData->error_msg = g_pErrorStrings[error_eads];
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if (opcode == 0x16) // ret?
|
||||
{
|
||||
instruction ^= 0x04400000; // make 'jmp #0'
|
||||
}
|
||||
else if (opcode == 0x17) // jmp?
|
||||
{
|
||||
// for jmp, we only get s, there is no d
|
||||
|
||||
// see if it's an immediate value for s
|
||||
if (!g_pElementizer->GetNext(bEof))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (g_pElementizer->GetType() == type_pound)
|
||||
{
|
||||
instruction |= 0x00400000;
|
||||
}
|
||||
else
|
||||
{
|
||||
g_pElementizer->Backup();
|
||||
}
|
||||
|
||||
// get s
|
||||
if (!GetTryValue(pass == 1 ? true : false, true, true))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
int s = GetResult();
|
||||
|
||||
// make sure it's in range
|
||||
if (s > 0x1FF)
|
||||
{
|
||||
g_pCompilerData->error = true;
|
||||
g_pCompilerData->error_msg = g_pErrorStrings[error_srccex];
|
||||
return false;
|
||||
}
|
||||
|
||||
// set s on instruction
|
||||
instruction |= s;
|
||||
}
|
||||
else // regular instruction get both d and s
|
||||
{
|
||||
// get d
|
||||
if (!GetTryValue(pass == 1 ? true : false, true, true))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
int d = GetResult();
|
||||
|
||||
// make sure it's in range
|
||||
if (d > 0x1FF)
|
||||
{
|
||||
g_pCompilerData->error = true;
|
||||
g_pCompilerData->error_msg = g_pErrorStrings[error_drcex];
|
||||
return false;
|
||||
}
|
||||
|
||||
// set d on instruction
|
||||
instruction |= (d << 9);
|
||||
|
||||
if (!g_pElementizer->GetElement(type_comma))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// see if it's an immediate value for s
|
||||
if (!g_pElementizer->GetNext(bEof))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (g_pElementizer->GetType() == type_pound)
|
||||
{
|
||||
instruction |= 0x00400000;
|
||||
}
|
||||
else
|
||||
{
|
||||
g_pElementizer->Backup();
|
||||
}
|
||||
|
||||
// get s
|
||||
if (!GetTryValue(pass == 1 ? true : false, true, true))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
int s = GetResult();
|
||||
|
||||
// make sure it's in range
|
||||
if (s > 0x1FF)
|
||||
{
|
||||
g_pCompilerData->error = true;
|
||||
g_pCompilerData->error_msg = g_pErrorStrings[error_srccex];
|
||||
return false;
|
||||
}
|
||||
|
||||
// set s on instruction
|
||||
instruction |= s;
|
||||
}
|
||||
|
||||
// check for effects
|
||||
bool bAfterComma = false;
|
||||
while (!bEof)
|
||||
{
|
||||
if (!g_pElementizer->GetNext(bEof))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (g_pElementizer->GetType() == type_asm_effect)
|
||||
{
|
||||
int effectValue = g_pElementizer->GetValue();
|
||||
|
||||
// don't allow wr/nr for r/w instructions
|
||||
if ((effectValue & 0x09) && (instruction >> 26) <= 2)
|
||||
{
|
||||
g_pCompilerData->error = true;
|
||||
g_pCompilerData->error_msg = g_pErrorStrings[error_micuwn];
|
||||
return false;
|
||||
}
|
||||
|
||||
// apply effect to instruction
|
||||
int temp = (effectValue & 0x38) << 20;
|
||||
instruction |= temp;
|
||||
instruction ^= temp;
|
||||
instruction |= ((effectValue & 0x07) << 23);
|
||||
|
||||
bool bComma = false;
|
||||
if (!GetCommaOrEnd(bComma))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (!bComma)
|
||||
{
|
||||
// got end, done with effects
|
||||
break;
|
||||
}
|
||||
|
||||
// got a comma, expecting another effect
|
||||
bAfterComma = true;
|
||||
}
|
||||
else if (bAfterComma)
|
||||
{
|
||||
// expected another effect after the comma
|
||||
g_pCompilerData->error = true;
|
||||
g_pCompilerData->error_msg = g_pErrorStrings[error_eaasme];
|
||||
return false;
|
||||
}
|
||||
else if (g_pElementizer->GetType() != type_end)
|
||||
{
|
||||
// if it wasn't an effect the first time in then it should be an end
|
||||
g_pCompilerData->error = true;
|
||||
g_pCompilerData->error_msg = g_pErrorStrings[error_eaaeoeol];
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
// we get here if we got no effect and got the proper end
|
||||
break;
|
||||
}
|
||||
}
|
||||
// enter instruction as 1 long
|
||||
if (!CompileDatBlocks_Enter(instruction, 1, 2))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CompileDatBlocks_CheckInstruction()
|
||||
{
|
||||
if (g_pElementizer->GetType() == type_asm_inst || g_pElementizer->IsDual())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
if (g_pElementizer->GetType() == type_binary)
|
||||
{
|
||||
if (g_pElementizer->GetOpType() == op_log_and || g_pElementizer->GetOpType() == op_log_or)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CompileDatBlocks_AsmCondition(bool& bEof, int pass, bool bSymbol, bool bResSymbol, int& size)
|
||||
{
|
||||
unsigned char condition = (unsigned char)(g_pElementizer->GetValue() & 0x000000FF);
|
||||
if (!g_pElementizer->GetNext(bEof))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (CompileDatBlocks_CheckInstruction())
|
||||
{
|
||||
return CompileDatBlocks_AsmInstruction(bEof, pass, bSymbol, bResSymbol, size, condition);
|
||||
}
|
||||
|
||||
g_pCompilerData->error = true;
|
||||
g_pCompilerData->error_msg = g_pErrorStrings[error_eaasmi];
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CompileDatBlocks()
|
||||
{
|
||||
int infoflag = 0;
|
||||
int ptr = g_pCompilerData->obj_ptr;
|
||||
int datstart = 0;
|
||||
int objstart = 0;
|
||||
|
||||
for (int pass = 0; pass < 2; pass++)
|
||||
{
|
||||
g_pCompilerData->obj_ptr = ptr;
|
||||
g_pCompilerData->asm_local = 0;
|
||||
g_pCompilerData->cog_org = 0;
|
||||
g_pCompilerData->orgx = 0;
|
||||
int size = 0;
|
||||
|
||||
bool bEof = false;
|
||||
g_pElementizer->Reset();
|
||||
|
||||
while(!bEof)
|
||||
{
|
||||
if(g_pElementizer->GetNextBlock(block_dat, bEof))
|
||||
{
|
||||
if (bEof)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
datstart = g_pCompilerData->source_start;
|
||||
objstart = g_pCompilerData->obj_ptr;
|
||||
|
||||
while (!bEof)
|
||||
{
|
||||
if (!g_pElementizer->GetNext(bEof))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (bEof)
|
||||
{
|
||||
break;
|
||||
}
|
||||
infoflag = 1;
|
||||
if (g_pElementizer->GetType() == type_end)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
g_pCompilerData->inf_start = g_pCompilerData->source_start;
|
||||
|
||||
// clear symbol flags
|
||||
bool bLocal = false;
|
||||
bool bSymbol = false;
|
||||
bool bResSymbol = false;
|
||||
|
||||
if (!CheckLocal(bLocal)) // bLocal will be set if it is a local
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
g_pCompilerData->inf_finish = g_pCompilerData->source_finish;
|
||||
|
||||
if (g_pElementizer->GetType() == type_undefined) // undefined here means it's a symbol
|
||||
{
|
||||
if (!bLocal)
|
||||
{
|
||||
if (!IncrementAsmLocal())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bSymbol = true;
|
||||
g_pElementizer->BackupSymbol();
|
||||
|
||||
if (!g_pElementizer->GetNext(bEof))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (g_pElementizer->GetType() == type_end)
|
||||
{
|
||||
if (bSymbol)
|
||||
{
|
||||
CompileDatBlocks_EnterSymbol(bResSymbol, size);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else if (g_pElementizer->GetType() == type_dat_byte ||
|
||||
g_pElementizer->GetType() == type_dat_word ||
|
||||
g_pElementizer->GetType() == type_dat_long ||
|
||||
g_pElementizer->GetType() == type_dat_long_res)
|
||||
{
|
||||
if (!bLocal)
|
||||
{
|
||||
if (!IncrementAsmLocal())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (pass == 0)
|
||||
{
|
||||
g_pCompilerData->error = true;
|
||||
g_pCompilerData->error_msg = g_pErrorStrings[error_siad];
|
||||
return false;
|
||||
}
|
||||
if (!g_pElementizer->GetNext(bEof))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (g_pElementizer->GetType() == type_end)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (g_pElementizer->GetType() == type_size)
|
||||
{
|
||||
if (!CompileDatBlocks_Data(bEof, pass, bSymbol, bResSymbol, size))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
else if (g_pElementizer->GetType() == type_file)
|
||||
{
|
||||
if (!CompileDatBlocks_File(bSymbol, bResSymbol, size))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
else if (g_pElementizer->GetType() == type_asm_dir)
|
||||
{
|
||||
if (!CompileDatBlocks_AsmDirective(bSymbol, bResSymbol, size))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
else if (g_pElementizer->GetType() == type_asm_cond)
|
||||
{
|
||||
if (!CompileDatBlocks_AsmCondition(bEof, pass, bSymbol, bResSymbol, size))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
else if (CompileDatBlocks_CheckInstruction())
|
||||
{
|
||||
if (!CompileDatBlocks_AsmInstruction(bEof, pass, bSymbol, bResSymbol, size, if_always))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (g_pElementizer->GetType() == type_block)
|
||||
{
|
||||
g_pElementizer->Backup();
|
||||
if (pass == 0)
|
||||
{
|
||||
CompileDatBlocks_EnterInfo(datstart, objstart);
|
||||
}
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
g_pCompilerData->error = true;
|
||||
g_pCompilerData->error_msg = g_pErrorStrings[error_eaunbwlo];
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (infoflag != 0 && pass == 0)
|
||||
{
|
||||
CompileDatBlocks_EnterInfo(datstart, objstart);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// TERMS OF USE: MIT License //
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy of this //
|
||||
// software and associated documentation files (the "Software"), to deal in the Software //
|
||||
// without restriction, including without limitation the rights to use, copy, modify, //
|
||||
// merge, publish, distribute, sublicense, and/or sell copies of the Software, and to //
|
||||
// permit persons to whom the Software is furnished to do so, subject to the following //
|
||||
// conditions: //
|
||||
// //
|
||||
// The above copyright notice and this permission notice shall be included in all copies //
|
||||
// or substantial portions of the Software. //
|
||||
// //
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, //
|
||||
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A //
|
||||
// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT //
|
||||
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION //
|
||||
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE //
|
||||
// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. //
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
755
Tools/unix/OpenSpin/PropellerCompiler/CompileExpression.cpp
Normal file
755
Tools/unix/OpenSpin/PropellerCompiler/CompileExpression.cpp
Normal file
@@ -0,0 +1,755 @@
|
||||
//////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// Propeller Spin/PASM Compiler //
|
||||
// (c)2012-2016 Parallax Inc. DBA Parallax Semiconductor. //
|
||||
// Adapted from Chip Gracey's x86 asm code by Roy Eltham //
|
||||
// See end of file for terms of use. //
|
||||
// //
|
||||
//////////////////////////////////////////////////////////////
|
||||
//
|
||||
// CompileExpression.cpp
|
||||
//
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
#include "Utilities.h"
|
||||
#include "PropellerCompilerInternal.h"
|
||||
#include "SymbolEngine.h"
|
||||
#include "Elementizer.h"
|
||||
#include "ErrorStrings.h"
|
||||
#include "CompileUtilities.h"
|
||||
|
||||
//
|
||||
//************************************************************************
|
||||
//* Expression Compiler *
|
||||
//************************************************************************
|
||||
//
|
||||
// Basic expression syntax rules: i.e. 4000/(||x*5)//127)+1
|
||||
//
|
||||
// Any one of these... Must be followed by any one of these...
|
||||
// ------------------------------------------------------------------
|
||||
// term binary operator
|
||||
// ) )
|
||||
// <end>
|
||||
//
|
||||
// Any one of these... Must be followed by any one of these... *
|
||||
// ------------------------------------------------------------------
|
||||
// unary operator term
|
||||
// binary operator unary operator
|
||||
// ( (
|
||||
//
|
||||
// * initial element of an expression
|
||||
//
|
||||
|
||||
// forward declarations
|
||||
bool CompileTerm();
|
||||
bool CompileSubExpression(int precedence);
|
||||
bool CompileTopExpression();
|
||||
|
||||
// Compile expression with sub-expressions
|
||||
bool CompileExpression()
|
||||
{
|
||||
if (!CompileTopExpression())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CompileTopExpression()
|
||||
{
|
||||
if (!CompileSubExpression(11))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CompileSubExpression_Term()
|
||||
{
|
||||
// get next element ignoring any leading +'s
|
||||
bool bEof = false;
|
||||
do
|
||||
{
|
||||
if (!g_pElementizer->GetNext(bEof))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
} while (g_pElementizer->GetType() == type_binary && g_pElementizer->GetOpType() == op_add);
|
||||
|
||||
if (!g_pElementizer->NegConToCon())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
g_pElementizer->SubToNeg();
|
||||
|
||||
int opType = g_pElementizer->GetOpType();
|
||||
|
||||
switch (g_pElementizer->GetType())
|
||||
{
|
||||
case type_atat:
|
||||
if (!CompileSubExpression(0))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (!EnterObj(0x97)) // memop byte+index+pbase+address
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (!EnterObj(0)) // address 0
|
||||
{
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
|
||||
case type_unary:
|
||||
if (!CompileSubExpression(g_pElementizer->GetValue())) // value = precedence for type_unary
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (!EnterObj((unsigned char)opType | 0xE0)) // math
|
||||
{
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
|
||||
case type_left:
|
||||
if (!CompileTopExpression())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (!g_pElementizer->GetElement(type_right))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
if (!CompileTerm())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CompileSubExpression(int precedence)
|
||||
{
|
||||
precedence--;
|
||||
if (precedence < 0)
|
||||
{
|
||||
if (!CompileSubExpression_Term())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!CompileSubExpression(precedence))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
for (;;)
|
||||
{
|
||||
bool bEof = false;
|
||||
if (!g_pElementizer->GetNext(bEof))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (g_pElementizer->GetType() != type_binary)
|
||||
{
|
||||
g_pElementizer->Backup();
|
||||
break;
|
||||
}
|
||||
// if we got here then it's type_binary (so the value is the precedence)
|
||||
if (g_pElementizer->GetValue() != precedence)
|
||||
{
|
||||
g_pElementizer->Backup();
|
||||
break;
|
||||
}
|
||||
int opType = g_pElementizer->GetOpType();
|
||||
if (!CompileSubExpression(precedence))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (!EnterObj((unsigned char)(opType | 0xE0)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
//
|
||||
// CompileTerm functions
|
||||
//
|
||||
|
||||
// compile constant(constantexpression)
|
||||
bool CompileTerm_ConExp()
|
||||
{
|
||||
if (!g_pElementizer->GetElement(type_left))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (!GetTryValue(true, false))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (!CompileConstant(GetResult()))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return g_pElementizer->GetElement(type_right);
|
||||
}
|
||||
|
||||
// compile string("constantstring")
|
||||
bool CompileTerm_ConStr()
|
||||
{
|
||||
if (g_pCompilerData->str_enable == false)
|
||||
{
|
||||
g_pCompilerData->error = true;
|
||||
g_pCompilerData->error_msg = g_pErrorStrings[error_snah];
|
||||
return false;
|
||||
}
|
||||
if (!g_pElementizer->GetElement(type_left))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (!StringConstant_GetIndex()) // get index in g_pCompilerData->str_index
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// get the string into the string constant buffer
|
||||
for (;;)
|
||||
{
|
||||
if (!GetTryValue(true, false))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
int value = GetResult();
|
||||
if (g_pCompilerData->intMode == 2 || value == 0 || value > 0xFF)
|
||||
{
|
||||
g_pCompilerData->error = true;
|
||||
g_pCompilerData->error_msg = g_pErrorStrings[error_scmr];
|
||||
return false;
|
||||
}
|
||||
if (!StringConstant_EnterChar((unsigned char)(value & 0xFF))) // add character to string constant buffer
|
||||
{
|
||||
return false;
|
||||
}
|
||||
// more characters?
|
||||
bool bComma = false;
|
||||
if (!GetCommaOrRight(bComma))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (!bComma)
|
||||
{
|
||||
// got right ')'
|
||||
break;
|
||||
}
|
||||
}
|
||||
StringConstant_EnterChar(0); // enter 0 terminator into string constant buffer
|
||||
|
||||
if (!EnterObj(0x87)) // (memcp byte+pbase+address)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
StringConstant_EnterPatch(); // enter string constant patch address
|
||||
|
||||
// enter two address bytes (patched later)
|
||||
if (!EnterObj(0x80))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return EnterObj(0);
|
||||
}
|
||||
|
||||
// compile float(integer)/round(float)/trunc(float)
|
||||
bool CompileTerm_FloatRoundTrunc()
|
||||
{
|
||||
g_pElementizer->Backup(); // backup to float/round/trunc
|
||||
|
||||
if (!GetTryValue(true, false))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return CompileConstant(GetResult());
|
||||
}
|
||||
|
||||
bool CompileTerm_Sub(unsigned char anchor, int value)
|
||||
{
|
||||
if (!EnterObj(anchor)) // drop anchor
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (!CompileParameters((value & 0x0000FF00) >> 8))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (!EnterObj(0x05)) // call sub
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return EnterObj((unsigned char)(value & 0xFF)); // index of sub
|
||||
}
|
||||
|
||||
// compile obj[].pub
|
||||
bool CompileTerm_ObjPub(unsigned char anchor, int value)
|
||||
{
|
||||
if (!EnterObj(anchor)) // drop anchor
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// check for [index]
|
||||
bool bIndex = false;
|
||||
int expSourcePtr = 0;
|
||||
if (!CheckIndex(bIndex, expSourcePtr))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!g_pElementizer->GetElement(type_dot))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// lookup the pub symbol
|
||||
if (!GetObjSymbol(type_objpub, (char)((value & 0x0000FF00) >> 8)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
int objPubValue = g_pElementizer->GetValue();
|
||||
|
||||
// compile any parameters the pub has
|
||||
if (!CompileParameters((objPubValue & 0x0000FF00) >> 8))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
unsigned char byteCode = 0x06; // call obj.pub
|
||||
if (bIndex)
|
||||
{
|
||||
if (!CompileOutOfSequenceExpression(expSourcePtr))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
byteCode = 0x07; // call obj[].pub
|
||||
}
|
||||
if (!EnterObj(byteCode))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!EnterObj((unsigned char)(value & 0xFF))) // index of obj
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return EnterObj((unsigned char)(objPubValue & 0xFF)); // index of objpub
|
||||
}
|
||||
|
||||
// compile obj[].pub\obj[]#con
|
||||
bool CompileTerm_ObjPubCon(int value)
|
||||
{
|
||||
if (!g_pElementizer->CheckElement(type_pound)) // check for obj#con
|
||||
{
|
||||
// not obj#con, so do obj[].pub
|
||||
return CompileTerm_ObjPub(0, value);
|
||||
}
|
||||
// lookup the symbol to get the value to compile
|
||||
if (!GetObjSymbol(type_objcon, (char)((value & 0x0000FF00) >> 8)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return CompileConstant(g_pElementizer->GetValue());
|
||||
}
|
||||
|
||||
// compile \sub or \obj
|
||||
bool CompileTerm_Try(unsigned char anchor)
|
||||
{
|
||||
bool bEof = false;
|
||||
if (!g_pElementizer->GetNext(bEof))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (g_pElementizer->GetType() == type_sub)
|
||||
{
|
||||
return CompileTerm_Sub(anchor, g_pElementizer->GetValue());
|
||||
}
|
||||
else if (g_pElementizer->GetType() == type_obj)
|
||||
{
|
||||
return CompileTerm_ObjPub(anchor, g_pElementizer->GetValue());
|
||||
}
|
||||
|
||||
g_pCompilerData->error = true;
|
||||
g_pCompilerData->error_msg = g_pErrorStrings[error_easoon];
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CompileLook(int column, int param)
|
||||
{
|
||||
column = column; // stop warning
|
||||
|
||||
param &= 0xFF; // we only care about the bottom byte
|
||||
|
||||
unsigned char byteCode = 0x35; // constant 0
|
||||
if (param < 0x80) // zero based?
|
||||
{
|
||||
byteCode += 1; // not, so make it a constant 1
|
||||
}
|
||||
if (!EnterObj(byteCode))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!BlockStack_CompileConstant()) // enter address constant
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!g_pElementizer->GetElement(type_left))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (!CompileExpression()) // compile primary value
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (!g_pElementizer->GetElement(type_colon))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
for (;;)
|
||||
{
|
||||
bool bRange = false;
|
||||
if (!CompileRange(bRange)) // compile (next) value/range
|
||||
{
|
||||
return false;
|
||||
}
|
||||
byteCode = (unsigned char)param;
|
||||
if (bRange)
|
||||
{
|
||||
byteCode |= 2;
|
||||
}
|
||||
if (!EnterObj(byteCode & 0x7F))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
bool bComma = false;
|
||||
if (!GetCommaOrRight(bComma))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (!bComma)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!EnterObj(0x0F)) // lookdone
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
BlockStack_Write(0, g_pCompilerData->obj_ptr); // set address
|
||||
return true;
|
||||
}
|
||||
|
||||
// compile 'lookup'/'lookdown'
|
||||
// this one compiles like a block (see InstructionBlockCompiler.cpp stuff)
|
||||
bool CompileTerm_Look(int value)
|
||||
{
|
||||
if (!BlockNest_New(type_i_look, 1))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!OptimizeBlock(0, value, &CompileLook))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
BlockNest_End();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CompileTerm_ClkMode()
|
||||
{
|
||||
if (!EnterObj(0x38)) // constant 4
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (!EnterObj(4))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return EnterObj(0x80); // read byte[]
|
||||
}
|
||||
|
||||
bool CompileTerm_ClkFreq()
|
||||
{
|
||||
if (!EnterObj(0x35)) // constant 0
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return EnterObj(0xC0); // read long[]
|
||||
}
|
||||
|
||||
bool CompileTerm_ChipVer()
|
||||
{
|
||||
if (!EnterObj(0x34)) // constant -1
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return EnterObj(0x80); // read byte[]
|
||||
}
|
||||
|
||||
bool CompileTerm_CogId()
|
||||
{
|
||||
if (!EnterObj(0x3F)) // reg op
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return EnterObj(0x89); // read id
|
||||
}
|
||||
|
||||
bool CompileTerm_Inst(int value)
|
||||
{
|
||||
if (!CompileParameters((value & 0xFF) >> 6))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return EnterObj((unsigned char)(value & 0x3F)); // instruction
|
||||
}
|
||||
|
||||
bool CompileTerm_CogNew(int value)
|
||||
{
|
||||
// see if first param is a sub
|
||||
if (!g_pElementizer->GetElement(type_left))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
bool bEof = false;
|
||||
if (!g_pElementizer->GetNext(bEof))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (g_pElementizer->GetType() == type_sub)
|
||||
{
|
||||
int subConstant = g_pElementizer->GetValue();
|
||||
|
||||
if (!g_pCompilerData->bFinalCompile && g_pCompilerData->bUnusedMethodElimination)
|
||||
{
|
||||
AddCogNewOrInit(g_pCompilerData->current_filename, subConstant & 0x000000FF);
|
||||
}
|
||||
|
||||
// it is a sub, so compile as cognew(subname(params),stack)
|
||||
if (!CompileParameters((g_pElementizer->GetValue() & 0x0000FF00) >> 8))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (!CompileConstant(subConstant))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (!g_pElementizer->GetElement(type_comma))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (!CompileExpression()) // compile stack expression
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (!g_pElementizer->GetElement(type_right))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (!EnterObj(0x15)) // run
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return EnterObj((unsigned char)(value & 0x3F)); // coginit
|
||||
}
|
||||
|
||||
// it is not a sub, so backup and compile as cognew(address, parameter)
|
||||
g_pElementizer->Backup();
|
||||
g_pElementizer->Backup();
|
||||
|
||||
if (!EnterObj(0x34)) // constant -1
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return CompileTerm_Inst(value);
|
||||
}
|
||||
|
||||
// compile @var
|
||||
bool CompileTerm_At()
|
||||
{
|
||||
unsigned char varType = 0;
|
||||
unsigned char varSize = 0;
|
||||
int varAddress = 0;
|
||||
int varIndexSourcePtr = 0;
|
||||
if (!GetVariable(varType, varSize, varAddress, varIndexSourcePtr))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (varType == type_reg || varType == type_spr)
|
||||
{
|
||||
g_pCompilerData->error = true;
|
||||
g_pCompilerData->error_msg = g_pErrorStrings[error_eamvaa];
|
||||
return false;
|
||||
}
|
||||
return CompileVariable(3, 0, varType, varSize, varAddress, varIndexSourcePtr);
|
||||
}
|
||||
|
||||
bool CompileTerm()
|
||||
{
|
||||
int type = g_pElementizer->GetType();
|
||||
int value = g_pElementizer->GetValue();
|
||||
|
||||
switch(type)
|
||||
{
|
||||
case type_con:
|
||||
case type_con_float:
|
||||
return CompileConstant(value);
|
||||
case type_conexp:
|
||||
return CompileTerm_ConExp();
|
||||
case type_constr:
|
||||
return CompileTerm_ConStr();
|
||||
case type_float:
|
||||
case type_round:
|
||||
case type_trunc:
|
||||
return CompileTerm_FloatRoundTrunc();
|
||||
case type_back:
|
||||
return CompileTerm_Try(0x02);
|
||||
case type_sub:
|
||||
return CompileTerm_Sub(0, value);
|
||||
case type_obj:
|
||||
return CompileTerm_ObjPubCon(value);
|
||||
case type_i_look:
|
||||
return CompileTerm_Look(value);
|
||||
case type_i_clkmode:
|
||||
return CompileTerm_ClkMode();
|
||||
case type_i_clkfreq:
|
||||
return CompileTerm_ClkFreq();
|
||||
case type_i_chipver:
|
||||
return CompileTerm_ChipVer();
|
||||
case type_i_cogid:
|
||||
return CompileTerm_CogId();
|
||||
case type_i_cognew:
|
||||
return CompileTerm_CogNew(value);
|
||||
case type_i_ar: // instruction always-returns
|
||||
case type_i_cr: // instruction can-return
|
||||
return CompileTerm_Inst(value);
|
||||
case type_at: // @var
|
||||
return CompileTerm_At();
|
||||
case type_inc: // assign pre-inc w/push ++var
|
||||
return CompileVariable_PreIncOrDec(0xA0);
|
||||
case type_dec: // assign pre-dec w/push --var
|
||||
return CompileVariable_PreIncOrDec(0xB0);
|
||||
case type_til: // assign sign-extern byte w/push ~var
|
||||
return CompileVariable_PreSignExtendOrRandom(0x90);
|
||||
case type_tiltil: // assign sign-extern word w/push ~~var
|
||||
return CompileVariable_PreSignExtendOrRandom(0x94);
|
||||
case type_rnd: // assign random forward w/push ?var
|
||||
return CompileVariable_PreSignExtendOrRandom(0x88);
|
||||
}
|
||||
|
||||
unsigned char varType = 0;
|
||||
unsigned char varSize = 0;
|
||||
int varAddress = 0;
|
||||
int varIndexSourcePtr = 0;
|
||||
bool bVariable = false;
|
||||
if (!CheckVariable(bVariable, varType, varSize, varAddress, varIndexSourcePtr))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (!bVariable)
|
||||
{
|
||||
g_pCompilerData->error = true;
|
||||
g_pCompilerData->error_msg = g_pErrorStrings[error_eaet];
|
||||
return false;
|
||||
}
|
||||
|
||||
// check for post-var modifier
|
||||
bool bEof = false;
|
||||
if (!g_pElementizer->GetNext(bEof))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
type = g_pElementizer->GetType();
|
||||
switch (type)
|
||||
{
|
||||
case type_inc: // assign post-inc w/push var++
|
||||
return CompileVariable_IncOrDec(0xA8, varType, varSize, varAddress, varIndexSourcePtr);
|
||||
case type_dec: // assign post-dec w/push var--
|
||||
return CompileVariable_IncOrDec(0xB8, varType, varSize, varAddress, varIndexSourcePtr);
|
||||
case type_rnd: // assign random reverse w/push var?
|
||||
return CompileVariable_Assign(0x8C, varType, varSize, varAddress, varIndexSourcePtr);
|
||||
case type_til: // assign post-clear w/push var~
|
||||
return CompileVariable_Assign(0x98, varType, varSize, varAddress, varIndexSourcePtr);
|
||||
case type_tiltil: // assign post-set w/push var~~
|
||||
return CompileVariable_Assign(0x9C, varType, varSize, varAddress, varIndexSourcePtr);
|
||||
case type_assign: // assign write w/push var :=
|
||||
return CompileVariable_Expression(0x80, varType, varSize, varAddress, varIndexSourcePtr);
|
||||
}
|
||||
|
||||
unsigned char varOperator = 0x80; // assign write w/push
|
||||
// var binaryop?
|
||||
if (type == type_binary)
|
||||
{
|
||||
varOperator = 0xC0; // assign math w/swapargs w/push
|
||||
varOperator |= (unsigned char)(g_pElementizer->GetOpType());
|
||||
|
||||
// check for '=' after binary op
|
||||
if (!g_pElementizer->GetNext(bEof))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (g_pElementizer->GetType() == type_equal)
|
||||
{
|
||||
return CompileVariable_Expression(varOperator, varType, varSize, varAddress, varIndexSourcePtr);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_pElementizer->Backup(); // not '=' so backup
|
||||
}
|
||||
}
|
||||
g_pElementizer->Backup(); // no post-var modifier, so backup
|
||||
return CompileVariable(0, varOperator, varType, varSize, varAddress, varIndexSourcePtr);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// TERMS OF USE: MIT License //
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy of this //
|
||||
// software and associated documentation files (the "Software"), to deal in the Software //
|
||||
// without restriction, including without limitation the rights to use, copy, modify, //
|
||||
// merge, publish, distribute, sublicense, and/or sell copies of the Software, and to //
|
||||
// permit persons to whom the Software is furnished to do so, subject to the following //
|
||||
// conditions: //
|
||||
// //
|
||||
// The above copyright notice and this permission notice shall be included in all copies //
|
||||
// or substantial portions of the Software. //
|
||||
// //
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, //
|
||||
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A //
|
||||
// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT //
|
||||
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION //
|
||||
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE //
|
||||
// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. //
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
404
Tools/unix/OpenSpin/PropellerCompiler/CompileInstruction.cpp
Normal file
404
Tools/unix/OpenSpin/PropellerCompiler/CompileInstruction.cpp
Normal file
@@ -0,0 +1,404 @@
|
||||
//////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// Propeller Spin/PASM Compiler //
|
||||
// (c)2012-2016 Parallax Inc. DBA Parallax Semiconductor. //
|
||||
// Adapted from Chip Gracey's x86 asm code by Roy Eltham //
|
||||
// See end of file for terms of use. //
|
||||
// //
|
||||
//////////////////////////////////////////////////////////////
|
||||
//
|
||||
// CompileInstruction.cpp
|
||||
//
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
#include "Utilities.h"
|
||||
#include "PropellerCompilerInternal.h"
|
||||
#include "SymbolEngine.h"
|
||||
#include "Elementizer.h"
|
||||
#include "ErrorStrings.h"
|
||||
#include "CompileUtilities.h"
|
||||
|
||||
// these are in CompileExpression.cpp
|
||||
extern bool CompileTerm_Try(unsigned char anchor);
|
||||
extern bool CompileTerm_Sub(unsigned char anchor, int value);
|
||||
extern bool CompileTerm_ObjPub(unsigned char anchor, int value);
|
||||
extern bool CompileTerm_CogNew(int value);
|
||||
extern bool CompileTerm_Inst(int value);
|
||||
|
||||
bool CompileInst_NextQuit(int value)
|
||||
{
|
||||
int blockNestPtr = g_pCompilerData->bnest_ptr;
|
||||
|
||||
unsigned char byteCode = 0;
|
||||
int caseDepth = 0;
|
||||
|
||||
// find repeat block
|
||||
for (;;)
|
||||
{
|
||||
if (blockNestPtr == 0)
|
||||
{
|
||||
g_pCompilerData->error = true;
|
||||
g_pCompilerData->error_msg = g_pErrorStrings[error_tioawarb];
|
||||
return false;
|
||||
}
|
||||
|
||||
unsigned char blockNestType = g_pCompilerData->bnest_type[blockNestPtr-1];
|
||||
|
||||
if (blockNestType == type_repeat)
|
||||
{
|
||||
byteCode = 0x04; // jmp 'quit'
|
||||
break;
|
||||
}
|
||||
else if (blockNestType == type_repeat_count)
|
||||
{
|
||||
byteCode = 0x0B; // jnz 'quit'
|
||||
break;
|
||||
}
|
||||
else if (blockNestType == type_if)
|
||||
{
|
||||
// ignore 'if' block nest(s)
|
||||
}
|
||||
else if (blockNestType == type_case) // allow nesting within 'case' block(s)
|
||||
{
|
||||
caseDepth += 8; // pop 2 longs for each nested 'case'
|
||||
}
|
||||
else
|
||||
{
|
||||
g_pCompilerData->error = true;
|
||||
g_pCompilerData->error_msg = g_pErrorStrings[error_internal];
|
||||
return false;
|
||||
}
|
||||
blockNestPtr--;
|
||||
}
|
||||
|
||||
if (caseDepth > 0)
|
||||
{
|
||||
if (!CompileConstant(caseDepth)) // enter pop count
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (!EnterObj(0x14)) // pop
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
int blockStackPtr = g_pCompilerData->bstack_base[blockNestPtr - 1];
|
||||
|
||||
if ((value & 0xFF) == 0)
|
||||
{
|
||||
// next
|
||||
if (!EnterObj(0x04)) // jmp 'next'
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return CompileAddress(g_pCompilerData->bstack[blockStackPtr]);
|
||||
}
|
||||
|
||||
// quit
|
||||
if (!EnterObj(byteCode)) // jmp/jnz 'quit'
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return CompileAddress(g_pCompilerData->bstack[blockStackPtr + 1]);
|
||||
}
|
||||
|
||||
bool CompileInst_AbortReturn(int value)
|
||||
{
|
||||
// preview next element
|
||||
bool bEof = false;
|
||||
if (!g_pElementizer->GetNext(bEof))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
g_pElementizer->Backup();
|
||||
|
||||
if (g_pElementizer->GetType() != type_end)
|
||||
{
|
||||
// there's an expression, compile it
|
||||
if (!CompileExpression())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
value |= 0x01; // +value
|
||||
}
|
||||
return EnterObj((unsigned char)(value & 0xFF));
|
||||
}
|
||||
|
||||
bool CompileInst_Reboot()
|
||||
{
|
||||
if (!EnterObj(0x37)) // constant 0x80
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (!EnterObj(0x06))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!EnterObj(0x35)) // constant 0
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return EnterObj(0x20); // clkset
|
||||
}
|
||||
|
||||
bool CompileInst_CogNew(int value)
|
||||
{
|
||||
return CompileTerm_CogNew(value ^ 0x04); // no push
|
||||
}
|
||||
|
||||
bool CompileInst_CogInit(int value)
|
||||
{
|
||||
int savedSourcePtr = g_pElementizer->GetSourcePtr();
|
||||
|
||||
if (!g_pElementizer->GetElement(type_left))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
int cogidSourcePtr = g_pElementizer->GetSourcePtr();
|
||||
if (!SkipExpression())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (!g_pElementizer->GetElement(type_comma))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// check for subroutine
|
||||
bool bEof = false;
|
||||
if (!g_pElementizer->GetNext(bEof))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (g_pElementizer->GetType() != type_sub)
|
||||
{
|
||||
// not subroutine, so backup
|
||||
g_pElementizer->SetSourcePtr(savedSourcePtr);
|
||||
|
||||
return CompileTerm_Inst(value); // compile assembly 'coginit'
|
||||
}
|
||||
|
||||
// compile subroutine 'cognew' (push params+index)
|
||||
int subConstant = g_pElementizer->GetValue();
|
||||
|
||||
if (!g_pCompilerData->bFinalCompile && g_pCompilerData->bUnusedMethodElimination)
|
||||
{
|
||||
AddCogNewOrInit(g_pCompilerData->current_filename, subConstant & 0x000000FF);
|
||||
}
|
||||
|
||||
if (!CompileParameters((g_pElementizer->GetValue() & 0x0000FF00) >> 8))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (!CompileConstant(subConstant))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (!g_pElementizer->GetElement(type_comma))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (!CompileExpression()) // compile stack expression
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (!g_pElementizer->GetElement(type_right))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (!EnterObj(0x15)) // run
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// compile 'cogid' exp
|
||||
if (!CompileOutOfSequenceExpression(cogidSourcePtr))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!EnterObj(0x3F)) // regop
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (!EnterObj(0x8F)) // read+dcurr
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (!EnterObj(0x37)) // constant mask
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (!EnterObj(0x61)) // -4
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (!EnterObj(0xD1)) // write long[base][index]
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return EnterObj(0x2C); // coginit
|
||||
}
|
||||
|
||||
bool CompileInst_InstCr(int value)
|
||||
{
|
||||
return CompileTerm_Inst(value ^ 0x04); // no push
|
||||
}
|
||||
|
||||
bool CompileInst_Unary(int value)
|
||||
{
|
||||
return CompileVariable_PreSignExtendOrRandom((unsigned char)(0x40 | (value & 0xFF)));
|
||||
}
|
||||
|
||||
bool CompileInst_Assign(unsigned char vOperator, unsigned char type, unsigned char size, int address, int indexSourcePtr)
|
||||
{
|
||||
if (!CompileExpression())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return CompileVariable(1, vOperator, type, size, address, indexSourcePtr);
|
||||
}
|
||||
|
||||
bool CompileInstruction()
|
||||
{
|
||||
int type = g_pElementizer->GetType();
|
||||
int value = g_pElementizer->GetValue();
|
||||
|
||||
switch(type)
|
||||
{
|
||||
case type_back:
|
||||
return CompileTerm_Try(0x03);
|
||||
case type_sub:
|
||||
return CompileTerm_Sub(0x01, value);
|
||||
case type_obj:
|
||||
return CompileTerm_ObjPub(0x01, value);
|
||||
case type_i_next_quit:
|
||||
return CompileInst_NextQuit(value);
|
||||
case type_i_abort_return:
|
||||
return CompileInst_AbortReturn(value);
|
||||
case type_i_reboot:
|
||||
return CompileInst_Reboot();
|
||||
case type_i_cognew:
|
||||
return CompileInst_CogNew(value);
|
||||
case type_i_coginit:
|
||||
return CompileInst_CogInit(value);
|
||||
case type_i_cr: // instruction can-return
|
||||
return CompileInst_InstCr(value);
|
||||
case type_i_nr: // instruction never-return
|
||||
return CompileTerm_Inst(value);
|
||||
|
||||
case type_inc: // assign pre-inc ++var
|
||||
return CompileVariable_PreIncOrDec(0x20);
|
||||
case type_dec: // assign pre-dec --var
|
||||
return CompileVariable_PreIncOrDec(0x30);
|
||||
case type_til: // assign sign-extern byte ~var
|
||||
return CompileVariable_PreSignExtendOrRandom(0x10);
|
||||
case type_tiltil: // assign sign-extern word ~~var
|
||||
return CompileVariable_PreSignExtendOrRandom(0x14);
|
||||
case type_rnd: // assign random forward ?var
|
||||
return CompileVariable_PreSignExtendOrRandom(0x08);
|
||||
}
|
||||
|
||||
g_pElementizer->SubToNeg();
|
||||
if (g_pElementizer->GetType() == type_unary)
|
||||
{
|
||||
return CompileInst_Unary(g_pElementizer->GetOpType());
|
||||
}
|
||||
|
||||
unsigned char varType = 0;
|
||||
unsigned char varSize = 0;
|
||||
int varAddress = 0;
|
||||
int varIndexSourcePtr = 0;
|
||||
bool bVariable = false;
|
||||
if (!CheckVariable(bVariable, varType, varSize, varAddress, varIndexSourcePtr))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (!bVariable)
|
||||
{
|
||||
g_pCompilerData->error = true;
|
||||
g_pCompilerData->error_msg = g_pErrorStrings[error_eaiov];
|
||||
return false;
|
||||
}
|
||||
|
||||
// check for post-var modifier
|
||||
bool bEof = false;
|
||||
if (!g_pElementizer->GetNext(bEof))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
type = g_pElementizer->GetType();
|
||||
switch (type)
|
||||
{
|
||||
case type_inc: // assign post-inc
|
||||
return CompileVariable_IncOrDec(0x28, varType, varSize, varAddress, varIndexSourcePtr);
|
||||
case type_dec: // assign post-dec
|
||||
return CompileVariable_IncOrDec(0x38, varType, varSize, varAddress, varIndexSourcePtr);
|
||||
case type_rnd: // assign random reverse
|
||||
return CompileVariable_Assign(0x0C, varType, varSize, varAddress, varIndexSourcePtr);
|
||||
case type_til: // assign post-clear
|
||||
return CompileVariable_Assign(0x18, varType, varSize, varAddress, varIndexSourcePtr);
|
||||
case type_tiltil: // assign post-set
|
||||
return CompileVariable_Assign(0x1C, varType, varSize, varAddress, varIndexSourcePtr);
|
||||
case type_assign:
|
||||
return CompileInst_Assign(0x1C, varType, varSize, varAddress, varIndexSourcePtr);
|
||||
}
|
||||
|
||||
// var binaryop?
|
||||
if (type == type_binary)
|
||||
{
|
||||
unsigned char varOperator = 0x40; // assign math w/swapargs
|
||||
varOperator |= (unsigned char)(g_pElementizer->GetOpType());
|
||||
|
||||
// check for '=' after binary op
|
||||
if (!g_pElementizer->GetNext(bEof))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (g_pElementizer->GetType() == type_equal)
|
||||
{
|
||||
return CompileVariable_Expression(varOperator, varType, varSize, varAddress, varIndexSourcePtr);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_pElementizer->Backup(); // not '=' so backup
|
||||
}
|
||||
}
|
||||
g_pElementizer->Backup(); // no post-var modifier, so backup
|
||||
|
||||
// error, so backup and reget variable for error display
|
||||
g_pElementizer->Backup();
|
||||
g_pElementizer->GetNext(bEof); // this won't fail here, because it already succeeded above
|
||||
|
||||
g_pCompilerData->error = true;
|
||||
g_pCompilerData->error_msg = g_pErrorStrings[error_vnao];
|
||||
return false;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// TERMS OF USE: MIT License //
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy of this //
|
||||
// software and associated documentation files (the "Software"), to deal in the Software //
|
||||
// without restriction, including without limitation the rights to use, copy, modify, //
|
||||
// merge, publish, distribute, sublicense, and/or sell copies of the Software, and to //
|
||||
// permit persons to whom the Software is furnished to do so, subject to the following //
|
||||
// conditions: //
|
||||
// //
|
||||
// The above copyright notice and this permission notice shall be included in all copies //
|
||||
// or substantial portions of the Software. //
|
||||
// //
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, //
|
||||
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A //
|
||||
// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT //
|
||||
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION //
|
||||
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE //
|
||||
// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. //
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
768
Tools/unix/OpenSpin/PropellerCompiler/CompileSpin.cpp
Normal file
768
Tools/unix/OpenSpin/PropellerCompiler/CompileSpin.cpp
Normal file
@@ -0,0 +1,768 @@
|
||||
///////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// Propeller Spin/PASM Compiler Command Line Tool 'OpenSpin' //
|
||||
// (c)2012-2016 Parallax Inc. DBA Parallax Semiconductor. //
|
||||
// See end of file for terms of use. //
|
||||
// //
|
||||
///////////////////////////////////////////////////////////////
|
||||
//
|
||||
// CompileSpin.cpp
|
||||
//
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "CompileSpin.h"
|
||||
#include "PropellerCompiler.h"
|
||||
#include "objectheap.h"
|
||||
#include "textconvert.h"
|
||||
#include "preprocess.h"
|
||||
#include "Utilities.h"
|
||||
|
||||
#define ObjFileStackLimit 16
|
||||
#define ListLimit 2000000
|
||||
#define DocLimit 2000000
|
||||
|
||||
static struct preprocess s_preprocessor;
|
||||
CompilerData* s_pCompilerData = 0;
|
||||
static int s_nObjStackPtr = 0;
|
||||
static bool s_bFinalCompile;
|
||||
|
||||
static CompilerConfig s_compilerConfig;
|
||||
static LoadFileFunc s_pLoadFileFunc = 0;
|
||||
static FreeFileBufferFunc s_pFreeFileBufferFunc = 0;
|
||||
static unsigned char* s_pCompileResultBuffer = 0;
|
||||
|
||||
static Heirarchy s_objectHeirarchy;
|
||||
|
||||
class ObjectNode : public HeirarchyNode
|
||||
{
|
||||
public:
|
||||
char* m_pFullPath;
|
||||
|
||||
ObjectNode()
|
||||
: m_pFullPath(0)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
static bool GetPASCIISource(char* pFilename)
|
||||
{
|
||||
// read in file to temp buffer, convert to PASCII, and assign to s_pCompilerData->source
|
||||
int nLength = 0;
|
||||
char* pRawBuffer = s_pLoadFileFunc(pFilename, &nLength, &s_pCompilerData->current_file_path);
|
||||
if (pRawBuffer)
|
||||
{
|
||||
char* pBuffer = 0;
|
||||
if (s_compilerConfig.bUsePreprocessor)
|
||||
{
|
||||
memoryfile mfile;
|
||||
mfile.buffer = pRawBuffer;
|
||||
mfile.length = nLength;
|
||||
mfile.readoffset = 0;
|
||||
pp_push_file_struct(&s_preprocessor, &mfile, pFilename);
|
||||
pp_run(&s_preprocessor);
|
||||
pBuffer = pp_finish(&s_preprocessor);
|
||||
nLength = (int)strlen(pBuffer);
|
||||
if (nLength == 0)
|
||||
{
|
||||
free(pBuffer);
|
||||
pBuffer = 0;
|
||||
}
|
||||
s_pFreeFileBufferFunc(pRawBuffer);
|
||||
}
|
||||
else
|
||||
{
|
||||
pBuffer = pRawBuffer;
|
||||
}
|
||||
|
||||
char* pPASCIIBuffer = new char[nLength+1];
|
||||
memset(pPASCIIBuffer, 0, nLength + 1);
|
||||
if (!UnicodeToPASCII(pBuffer, nLength, pPASCIIBuffer, s_compilerConfig.bUsePreprocessor))
|
||||
{
|
||||
printf("Unrecognized text encoding format!\n");
|
||||
delete [] pPASCIIBuffer;
|
||||
if (s_compilerConfig.bUsePreprocessor)
|
||||
{
|
||||
free(pBuffer);
|
||||
}
|
||||
else
|
||||
{
|
||||
s_pFreeFileBufferFunc(pRawBuffer);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// clean up any previous buffer
|
||||
if (s_pCompilerData->source)
|
||||
{
|
||||
delete [] s_pCompilerData->source;
|
||||
}
|
||||
|
||||
s_pCompilerData->source = pPASCIIBuffer;
|
||||
|
||||
if (s_compilerConfig.bUsePreprocessor)
|
||||
{
|
||||
free(pBuffer);
|
||||
}
|
||||
else
|
||||
{
|
||||
s_pFreeFileBufferFunc(pRawBuffer);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
s_pCompilerData->source = NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void CleanupMemory(bool bUnusedMethodData = true)
|
||||
{
|
||||
delete s_objectHeirarchy.m_pRoot;
|
||||
s_objectHeirarchy.m_pRoot = 0;
|
||||
|
||||
if ( s_pCompilerData )
|
||||
{
|
||||
delete [] s_pCompilerData->list;
|
||||
delete [] s_pCompilerData->doc;
|
||||
delete [] s_pCompilerData->obj;
|
||||
delete [] s_pCompilerData->source;
|
||||
}
|
||||
CleanObjectHeap();
|
||||
if (bUnusedMethodData)
|
||||
{
|
||||
CleanUpUnusedMethodData();
|
||||
}
|
||||
Cleanup();
|
||||
if (s_pCompileResultBuffer != 0)
|
||||
{
|
||||
delete [] s_pCompileResultBuffer;
|
||||
s_pCompileResultBuffer = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void PrintError(const char* pFilename, const char* pErrorString)
|
||||
{
|
||||
int lineNumber = 1;
|
||||
int column = 1;
|
||||
int offsetToStartOfLine = -1;
|
||||
int offsetToEndOfLine = -1;
|
||||
int offendingItemStart = 0;
|
||||
int offendingItemEnd = 0;
|
||||
|
||||
GetErrorInfo(lineNumber, column, offsetToStartOfLine, offsetToEndOfLine, offendingItemStart, offendingItemEnd);
|
||||
|
||||
printf("%s(%d:%d) : error : %s\n", pFilename, lineNumber, column, pErrorString);
|
||||
|
||||
if ( offendingItemStart == offendingItemEnd && s_pCompilerData->source[offendingItemStart] == 0 )
|
||||
{
|
||||
printf("Line:\nEnd Of File\nOffending Item: N/A\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
char* errorLine = 0;
|
||||
char* errorItem = 0;
|
||||
|
||||
if (offendingItemEnd - offendingItemStart > 0)
|
||||
{
|
||||
errorLine = new char[(offsetToEndOfLine - offsetToStartOfLine) + 1];
|
||||
strncpy(errorLine, &s_pCompilerData->source[offsetToStartOfLine], offsetToEndOfLine - offsetToStartOfLine);
|
||||
errorLine[offsetToEndOfLine - offsetToStartOfLine] = 0;
|
||||
}
|
||||
|
||||
if (offendingItemEnd - offendingItemStart > 0)
|
||||
{
|
||||
errorItem = new char[(offendingItemEnd - offendingItemStart) + 1];
|
||||
strncpy(errorItem, &s_pCompilerData->source[offendingItemStart], offendingItemEnd - offendingItemStart);
|
||||
errorItem[offendingItemEnd - offendingItemStart] = 0;
|
||||
}
|
||||
|
||||
printf("Line:\n%s\nOffending Item: %s\n", errorLine ? errorLine : "N/A", errorItem ? errorItem : "N/A");
|
||||
|
||||
delete [] errorLine;
|
||||
delete [] errorItem;
|
||||
}
|
||||
}
|
||||
|
||||
static bool CheckForCircularReference(ObjectNode* pObjectNode)
|
||||
{
|
||||
ObjectNode* pCurrentNode = pObjectNode;
|
||||
while (pCurrentNode->m_pParent)
|
||||
{
|
||||
ObjectNode* pParent = (ObjectNode*)(pCurrentNode->m_pParent);
|
||||
if (strcmp(pObjectNode->m_pFullPath, pParent->m_pFullPath) == 0)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
pCurrentNode = pParent;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool CompileRecursively(char* pFilename, int& nCompileIndex, ObjectNode* pParentNode)
|
||||
{
|
||||
nCompileIndex++;
|
||||
if (s_nObjStackPtr > 0 && (!s_compilerConfig.bQuiet || s_compilerConfig.bFileTreeOutputOnly))
|
||||
{
|
||||
// only do this if UME is off or if it's the final compile when UME is on
|
||||
if (!s_compilerConfig.bUnusedMethodElimination || s_pCompilerData->bFinalCompile)
|
||||
{
|
||||
char spaces[] = " \0";
|
||||
printf("%s|-%s\n", &spaces[32-(s_nObjStackPtr<<1)], pFilename);
|
||||
}
|
||||
}
|
||||
s_nObjStackPtr++;
|
||||
if (s_nObjStackPtr > ObjFileStackLimit)
|
||||
{
|
||||
printf("%s : error : Object nesting exceeds limit of %d levels.\n", pFilename, ObjFileStackLimit);
|
||||
return false;
|
||||
}
|
||||
|
||||
void *definestate = 0;
|
||||
if (s_compilerConfig.bUsePreprocessor)
|
||||
{
|
||||
definestate = pp_get_define_state(&s_preprocessor);
|
||||
}
|
||||
if (!GetPASCIISource(pFilename))
|
||||
{
|
||||
printf("%s : error : Can not find/open file.\n", pFilename);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!s_pCompilerData->bFinalCompile && s_compilerConfig.bUnusedMethodElimination)
|
||||
{
|
||||
AddObjectName(pFilename, nCompileIndex);
|
||||
}
|
||||
|
||||
strcpy(s_pCompilerData->current_filename, pFilename);
|
||||
char* pExtension = strstr(s_pCompilerData->current_filename, ".spin");
|
||||
if (pExtension != 0)
|
||||
{
|
||||
*pExtension = 0;
|
||||
}
|
||||
|
||||
ObjectNode* pObjectNode = new ObjectNode();
|
||||
pObjectNode->m_pFullPath = s_pCompilerData->current_file_path;
|
||||
pObjectNode->m_pParent = pParentNode;
|
||||
s_objectHeirarchy.AddNode(pObjectNode, pParentNode);
|
||||
if (CheckForCircularReference(pObjectNode))
|
||||
{
|
||||
printf("%s : error : Illegal Circular Reference\n", pFilename);
|
||||
return false;
|
||||
}
|
||||
|
||||
// first pass on object
|
||||
const char* pErrorString = Compile1();
|
||||
if (pErrorString != 0)
|
||||
{
|
||||
PrintError(pFilename, pErrorString);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (s_pCompilerData->obj_files > 0)
|
||||
{
|
||||
char filenames[file_limit*256];
|
||||
|
||||
int numObjects = s_pCompilerData->obj_files;
|
||||
for (int i = 0; i < numObjects; i++)
|
||||
{
|
||||
// copy the obj filename appending .spin if it doesn't have it.
|
||||
strcpy(&filenames[i<<8], &(s_pCompilerData->obj_filenames[i<<8]));
|
||||
if (strstr(&filenames[i<<8], ".spin") == NULL)
|
||||
{
|
||||
strcat(&filenames[i<<8], ".spin");
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < numObjects; i++)
|
||||
{
|
||||
if (!CompileRecursively(&filenames[i<<8], nCompileIndex, pObjectNode))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// redo first pass on parent object
|
||||
if (s_compilerConfig.bUsePreprocessor)
|
||||
{
|
||||
// undo any defines in sub-objects
|
||||
pp_restore_define_state(&s_preprocessor, definestate);
|
||||
}
|
||||
if (!GetPASCIISource(pFilename))
|
||||
{
|
||||
printf("%s : error : Can not find/open file.\n", pFilename);
|
||||
return false;
|
||||
}
|
||||
|
||||
strcpy(s_pCompilerData->current_filename, pFilename);
|
||||
pExtension = strstr(s_pCompilerData->current_filename, ".spin");
|
||||
if (pExtension != 0)
|
||||
{
|
||||
*pExtension = 0;
|
||||
}
|
||||
pErrorString = Compile1();
|
||||
if (pErrorString != 0)
|
||||
{
|
||||
PrintError(pFilename, pErrorString);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!CopyObjectsFromHeap(s_pCompilerData, filenames))
|
||||
{
|
||||
printf("%s : error : Object files exceed 128k.\n", pFilename);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// load all DAT files
|
||||
if (s_pCompilerData->dat_files > 0)
|
||||
{
|
||||
int p = 0;
|
||||
for (int i = 0; i < s_pCompilerData->dat_files; i++)
|
||||
{
|
||||
// Get DAT's Files
|
||||
|
||||
// Get name information
|
||||
char filename[256];
|
||||
strcpy(&filename[0], &(s_pCompilerData->dat_filenames[i<<8]));
|
||||
|
||||
// Load file and add to dat_data buffer
|
||||
s_pCompilerData->dat_lengths[i] = -1;
|
||||
char* pFilePath = 0;
|
||||
char* pBuffer = s_pLoadFileFunc(&filename[0], &s_pCompilerData->dat_lengths[i], &pFilePath);
|
||||
|
||||
if (s_pCompilerData->dat_lengths[i] == -1)
|
||||
{
|
||||
s_pCompilerData->dat_lengths[i] = 0;
|
||||
printf("Cannot find/open dat file: %s \n", &filename[0]);
|
||||
return false;
|
||||
}
|
||||
if (p + s_pCompilerData->dat_lengths[i] > data_limit)
|
||||
{
|
||||
printf("%s : error : DAT files exceed 128k.\n", pFilename);
|
||||
return false;
|
||||
}
|
||||
memcpy(&(s_pCompilerData->dat_data[p]), pBuffer, s_pCompilerData->dat_lengths[i]);
|
||||
s_pFreeFileBufferFunc(pBuffer);
|
||||
s_pCompilerData->dat_offsets[i] = p;
|
||||
p += s_pCompilerData->dat_lengths[i];
|
||||
}
|
||||
}
|
||||
|
||||
// second pass of object
|
||||
pErrorString = Compile2();
|
||||
if (pErrorString != 0)
|
||||
{
|
||||
PrintError(pFilename, pErrorString);
|
||||
return false;
|
||||
}
|
||||
|
||||
// only do this check if UME is off or if it's the final compile when UME is on
|
||||
if (!s_compilerConfig.bUnusedMethodElimination || s_pCompilerData->bFinalCompile)
|
||||
{
|
||||
// Check to make sure object fits into 32k (or eeprom size if specified as larger than 32k)
|
||||
unsigned int i = 0x10 + s_pCompilerData->psize + s_pCompilerData->vsize + (s_pCompilerData->stack_requirement << 2);
|
||||
if ((s_pCompilerData->compile_mode == 0) && (i > s_pCompilerData->eeprom_size))
|
||||
{
|
||||
printf("%s : error : Object exceeds runtime memory limit by %d longs.\n", pFilename, (i - s_pCompilerData->eeprom_size) >> 2);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// save this object in the heap
|
||||
if (!AddObjectToHeap(pFilename, s_pCompilerData))
|
||||
{
|
||||
printf("%s : error : Object Heap Overflow.\n", pFilename);
|
||||
return false;
|
||||
}
|
||||
s_nObjStackPtr--;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool ComposeRAM(unsigned char** ppBuffer, int& bufferSize)
|
||||
{
|
||||
if (!s_compilerConfig.bDATonly)
|
||||
{
|
||||
unsigned int varsize = s_pCompilerData->vsize; // variable size (in bytes)
|
||||
unsigned int codsize = s_pCompilerData->psize; // code size (in bytes)
|
||||
unsigned int pubaddr = *((unsigned short*)&(s_pCompilerData->obj[8])); // address of first public method
|
||||
unsigned int publocs = *((unsigned short*)&(s_pCompilerData->obj[10])); // number of stack variables (locals), in bytes, for the first public method
|
||||
unsigned int pbase = 0x0010; // base of object code
|
||||
unsigned int vbase = pbase + codsize; // variable base = object base + code size
|
||||
unsigned int dbase = vbase + varsize + 8; // data base = variable base + variable size + 8
|
||||
unsigned int pcurr = pbase + pubaddr; // Current program start = object base + public address (first public method)
|
||||
unsigned int dcurr = dbase + 4 + (s_pCompilerData->first_pub_parameters << 2) + publocs; // current data stack pointer = data base + 4 + FirstParams*4 + publocs
|
||||
|
||||
if (s_compilerConfig.bBinary)
|
||||
{
|
||||
// reset ram
|
||||
*ppBuffer = new unsigned char[vbase];
|
||||
memset(*ppBuffer, 0, vbase);
|
||||
bufferSize = vbase;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (vbase + 8 > s_compilerConfig.eeprom_size)
|
||||
{
|
||||
printf("ERROR: eeprom size exceeded by %d longs.\n", (vbase + 8 - s_compilerConfig.eeprom_size) >> 2);
|
||||
return false;
|
||||
}
|
||||
// reset ram
|
||||
*ppBuffer = new unsigned char[s_compilerConfig.eeprom_size];
|
||||
memset(*ppBuffer, 0, s_compilerConfig.eeprom_size);
|
||||
bufferSize = s_compilerConfig.eeprom_size;
|
||||
(*ppBuffer)[dbase-8] = 0xFF;
|
||||
(*ppBuffer)[dbase-7] = 0xFF;
|
||||
(*ppBuffer)[dbase-6] = 0xF9;
|
||||
(*ppBuffer)[dbase-5] = 0xFF;
|
||||
(*ppBuffer)[dbase-4] = 0xFF;
|
||||
(*ppBuffer)[dbase-3] = 0xFF;
|
||||
(*ppBuffer)[dbase-2] = 0xF9;
|
||||
(*ppBuffer)[dbase-1] = 0xFF;
|
||||
}
|
||||
|
||||
// set clock frequency and clock mode
|
||||
*((int*)&((*ppBuffer)[0])) = s_pCompilerData->clkfreq;
|
||||
(*ppBuffer)[4] = s_pCompilerData->clkmode;
|
||||
|
||||
// set interpreter parameters
|
||||
((unsigned short*)&((*ppBuffer)[4]))[1] = (unsigned short)pbase; // always 0x0010
|
||||
((unsigned short*)&((*ppBuffer)[4]))[2] = (unsigned short)vbase;
|
||||
((unsigned short*)&((*ppBuffer)[4]))[3] = (unsigned short)dbase;
|
||||
((unsigned short*)&((*ppBuffer)[4]))[4] = (unsigned short)pcurr;
|
||||
((unsigned short*)&((*ppBuffer)[4]))[5] = (unsigned short)dcurr;
|
||||
|
||||
// set code
|
||||
memcpy(&((*ppBuffer)[pbase]), &(s_pCompilerData->obj[4]), codsize);
|
||||
|
||||
// install ram checksum byte
|
||||
unsigned char sum = 0;
|
||||
for (unsigned int i = 0; i < vbase; i++)
|
||||
{
|
||||
sum = sum + (*ppBuffer)[i];
|
||||
}
|
||||
(*ppBuffer)[5] = (unsigned char)((-(sum+2028)) );
|
||||
}
|
||||
else
|
||||
{
|
||||
unsigned int objsize = *((unsigned short*)&(s_pCompilerData->obj[4]));
|
||||
if (s_pCompilerData->psize > 65535)
|
||||
{
|
||||
objsize = s_pCompilerData->psize;
|
||||
}
|
||||
unsigned int size = objsize - 4 - (s_pCompilerData->obj[7] * 4);
|
||||
*ppBuffer = new unsigned char[size];
|
||||
bufferSize = size;
|
||||
memcpy(&((*ppBuffer)[0]), &(s_pCompilerData->obj[8 + (s_pCompilerData->obj[7] * 4)]), size);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void DumpSymbols()
|
||||
{
|
||||
for (int i = 0; i < s_pCompilerData->info_count; i++)
|
||||
{
|
||||
char szTemp[256];
|
||||
szTemp[0] = '*';
|
||||
szTemp[1] = 0;
|
||||
int length = 0;
|
||||
int start = 0;
|
||||
if (s_pCompilerData->info_type[i] == info_pub || s_pCompilerData->info_type[i] == info_pri)
|
||||
{
|
||||
length = s_pCompilerData->info_data3[i] - s_pCompilerData->info_data2[i];
|
||||
start = s_pCompilerData->info_data2[i];
|
||||
}
|
||||
else if (s_pCompilerData->info_type[i] != info_dat && s_pCompilerData->info_type[i] != info_dat_symbol)
|
||||
{
|
||||
length = s_pCompilerData->info_finish[i] - s_pCompilerData->info_start[i];
|
||||
start = s_pCompilerData->info_start[i];
|
||||
}
|
||||
|
||||
if (length > 0 && length < 256)
|
||||
{
|
||||
strncpy(szTemp, &s_pCompilerData->source[start], length);
|
||||
szTemp[length] = 0;
|
||||
}
|
||||
|
||||
switch(s_pCompilerData->info_type[i])
|
||||
{
|
||||
case info_con:
|
||||
printf("CON, %s, %d\n", szTemp, s_pCompilerData->info_data0[i]);
|
||||
break;
|
||||
case info_con_float:
|
||||
printf("CONF, %s, %f\n", szTemp, *((float*)&(s_pCompilerData->info_data0[i])));
|
||||
break;
|
||||
case info_pub_param:
|
||||
{
|
||||
char szTemp2[256];
|
||||
szTemp2[0] = '*';
|
||||
szTemp2[1] = 0;
|
||||
length = s_pCompilerData->info_data3[i] - s_pCompilerData->info_data2[i];
|
||||
start = s_pCompilerData->info_data2[i];
|
||||
if (length > 0 && length < 256)
|
||||
{
|
||||
strncpy(szTemp2, &s_pCompilerData->source[start], length);
|
||||
szTemp2[length] = 0;
|
||||
}
|
||||
printf("PARAM, %s, %s, %d, %d\n", szTemp2, szTemp, s_pCompilerData->info_data0[i], s_pCompilerData->info_data1[i]);
|
||||
}
|
||||
break;
|
||||
case info_pub:
|
||||
printf("PUB, %s, %d, %d\n", szTemp, s_pCompilerData->info_data4[i] & 0xFFFF, s_pCompilerData->info_data4[i] >> 16);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void DumpList()
|
||||
{
|
||||
size_t listOffset = 0;
|
||||
while (listOffset < s_pCompilerData->list_length)
|
||||
{
|
||||
char* pTemp = strstr(&(s_pCompilerData->list[listOffset]), "\r");
|
||||
if (pTemp)
|
||||
{
|
||||
*pTemp = 0;
|
||||
}
|
||||
printf("%s\n", &(s_pCompilerData->list[listOffset]));
|
||||
if (pTemp)
|
||||
{
|
||||
*pTemp = 0x0D;
|
||||
listOffset += (pTemp - &(s_pCompilerData->list[listOffset])) + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
listOffset += strlen(&(s_pCompilerData->list[listOffset]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void DumpDoc()
|
||||
{
|
||||
size_t docOffset = 0;
|
||||
while (docOffset < s_pCompilerData->doc_length)
|
||||
{
|
||||
char* pTemp = strstr(&(s_pCompilerData->doc[docOffset]), "\r");
|
||||
if (pTemp)
|
||||
{
|
||||
*pTemp = 0;
|
||||
}
|
||||
printf("%s\n", &(s_pCompilerData->doc[docOffset]));
|
||||
if (pTemp)
|
||||
{
|
||||
*pTemp = 0x0D;
|
||||
docOffset += (pTemp - &(s_pCompilerData->doc[docOffset])) + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
docOffset += strlen(&(s_pCompilerData->doc[docOffset]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void InitCompiler(CompilerConfig* pCompilerConfig, LoadFileFunc pLoadFileFunc, FreeFileBufferFunc pFreeFileBufferFunc)
|
||||
{
|
||||
s_nObjStackPtr = 0;
|
||||
s_pCompilerData = 0;
|
||||
s_bFinalCompile = false;
|
||||
s_pCompileResultBuffer = 0;
|
||||
|
||||
if (pCompilerConfig)
|
||||
{
|
||||
s_compilerConfig = *pCompilerConfig;
|
||||
}
|
||||
|
||||
s_pLoadFileFunc = pLoadFileFunc;
|
||||
s_pFreeFileBufferFunc = pFreeFileBufferFunc;
|
||||
|
||||
pp_setFileFunctions(pLoadFileFunc, pFreeFileBufferFunc);
|
||||
pp_init(&s_preprocessor, s_compilerConfig.bAlternatePreprocessorMode);
|
||||
pp_setcomments(&s_preprocessor, "\'", "{", "}");
|
||||
}
|
||||
|
||||
void SetDefine(const char* pName, const char* pValue)
|
||||
{
|
||||
pp_define(&s_preprocessor, pName, pValue);
|
||||
}
|
||||
|
||||
unsigned char* CompileSpin(char* pFilename, int* pnResultLength)
|
||||
{
|
||||
*pnResultLength = 0;
|
||||
|
||||
if (s_compilerConfig.bFileTreeOutputOnly)
|
||||
{
|
||||
printf("%s\n", pFilename);
|
||||
}
|
||||
|
||||
if (s_compilerConfig.bUnusedMethodElimination)
|
||||
{
|
||||
InitUnusedMethodData();
|
||||
}
|
||||
|
||||
int nOriginalSize = 0;
|
||||
|
||||
restart_compile:
|
||||
s_pCompilerData = InitStruct();
|
||||
s_pCompilerData->bUnusedMethodElimination = s_compilerConfig.bUnusedMethodElimination;
|
||||
s_pCompilerData->bFinalCompile = s_bFinalCompile;
|
||||
|
||||
s_pCompilerData->list = new char[ListLimit];
|
||||
s_pCompilerData->list_limit = ListLimit;
|
||||
memset(s_pCompilerData->list, 0, ListLimit);
|
||||
|
||||
if (s_compilerConfig.bDocMode && !s_compilerConfig.bDATonly)
|
||||
{
|
||||
s_pCompilerData->doc = new char[DocLimit];
|
||||
s_pCompilerData->doc_limit = DocLimit;
|
||||
memset(s_pCompilerData->doc, 0, DocLimit);
|
||||
}
|
||||
else
|
||||
{
|
||||
s_pCompilerData->doc = 0;
|
||||
s_pCompilerData->doc_limit = 0;
|
||||
}
|
||||
s_pCompilerData->bDATonly = s_compilerConfig.bDATonly;
|
||||
s_pCompilerData->bBinary = s_compilerConfig.bBinary;
|
||||
s_pCompilerData->eeprom_size = s_compilerConfig.eeprom_size;
|
||||
|
||||
// allocate space for obj based on eeprom size command line option
|
||||
s_pCompilerData->obj_limit = s_compilerConfig.eeprom_size > min_obj_limit ? s_compilerConfig.eeprom_size : min_obj_limit;
|
||||
s_pCompilerData->obj = new unsigned char[s_pCompilerData->obj_limit];
|
||||
|
||||
// copy filename into obj_title, and chop off the .spin
|
||||
strcpy(s_pCompilerData->obj_title, pFilename);
|
||||
char* pExtension = strstr(&s_pCompilerData->obj_title[0], ".spin");
|
||||
if (pExtension != 0)
|
||||
{
|
||||
*pExtension = 0;
|
||||
}
|
||||
|
||||
int nCompileIndex = 0;
|
||||
if (!CompileRecursively(pFilename, nCompileIndex, 0))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!s_compilerConfig.bQuiet)
|
||||
{
|
||||
// only do this if UME is off or if it's the final compile when UME is on
|
||||
if (!s_compilerConfig.bUnusedMethodElimination || s_bFinalCompile)
|
||||
{
|
||||
printf("Done.\n");
|
||||
}
|
||||
}
|
||||
|
||||
if (!s_compilerConfig.bFileTreeOutputOnly && !s_compilerConfig.bFileListOutputOnly && !s_compilerConfig.bDumpSymbols)
|
||||
{
|
||||
if (!s_bFinalCompile && s_compilerConfig.bUnusedMethodElimination)
|
||||
{
|
||||
nOriginalSize = s_pCompilerData->psize;
|
||||
FindUnusedMethods(s_pCompilerData);
|
||||
s_bFinalCompile = true;
|
||||
CleanupMemory(false);
|
||||
goto restart_compile;
|
||||
}
|
||||
int bufferSize = 0;
|
||||
if (!ComposeRAM(&s_pCompileResultBuffer, bufferSize))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!s_compilerConfig.bQuiet)
|
||||
{
|
||||
if (s_compilerConfig.bUnusedMethodElimination)
|
||||
{
|
||||
printf("Unused Method Elimination:\n");
|
||||
if ((nOriginalSize - s_pCompilerData->psize) > 0)
|
||||
{
|
||||
if (s_compilerConfig.bVerbose)
|
||||
{
|
||||
if (s_pCompilerData->unused_obj_files)
|
||||
{
|
||||
printf("Unused Objects:\n");
|
||||
for(int i = 0; i < s_pCompilerData->unused_obj_files; i++)
|
||||
{
|
||||
printf("%s\n", &(s_pCompilerData->obj_unused[i<<8]));
|
||||
}
|
||||
}
|
||||
if (s_pCompilerData->unused_methods)
|
||||
{
|
||||
printf("Unused Methods:\n");
|
||||
for(int i = 0; i < s_pCompilerData->unused_methods; i++)
|
||||
{
|
||||
printf("%s\n", &(s_pCompilerData->method_unused[i*symbol_limit]));
|
||||
}
|
||||
}
|
||||
if (s_pCompilerData->unused_methods || s_pCompilerData->unused_obj_files)
|
||||
{
|
||||
printf("---------------\n");
|
||||
}
|
||||
}
|
||||
printf("%5d methods removed\n%5d objects removed\n%5d bytes saved\n", s_pCompilerData->unused_methods, s_pCompilerData->unused_obj_files, nOriginalSize - s_pCompilerData->psize );
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("Nothing removed.\n");
|
||||
}
|
||||
printf("--------------------------\n");
|
||||
}
|
||||
printf("Program size is %d bytes\n", bufferSize);
|
||||
}
|
||||
*pnResultLength = bufferSize;
|
||||
}
|
||||
|
||||
if (s_compilerConfig.bDumpSymbols)
|
||||
{
|
||||
DumpSymbols();
|
||||
}
|
||||
|
||||
if (s_compilerConfig.bVerbose && !s_compilerConfig.bQuiet && !s_compilerConfig.bDATonly)
|
||||
{
|
||||
DumpList();
|
||||
}
|
||||
|
||||
if (s_compilerConfig.bDocMode && s_compilerConfig.bVerbose && !s_compilerConfig.bQuiet && !s_compilerConfig.bDATonly)
|
||||
{
|
||||
DumpDoc();
|
||||
}
|
||||
|
||||
return s_pCompileResultBuffer;
|
||||
}
|
||||
|
||||
void ShutdownCompiler()
|
||||
{
|
||||
pp_clear_define_state(&s_preprocessor);
|
||||
CleanupMemory();
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// TERMS OF USE: MIT License //
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy of this //
|
||||
// software and associated documentation files (the "Software"), to deal in the Software //
|
||||
// without restriction, including without limitation the rights to use, copy, modify, //
|
||||
// merge, publish, distribute, sublicense, and/or sell copies of the Software, and to //
|
||||
// permit persons to whom the Software is furnished to do so, subject to the following //
|
||||
// conditions: //
|
||||
// //
|
||||
// The above copyright notice and this permission notice shall be included in all copies //
|
||||
// or substantial portions of the Software. //
|
||||
// //
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, //
|
||||
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A //
|
||||
// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT //
|
||||
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION //
|
||||
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE //
|
||||
// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. //
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
76
Tools/unix/OpenSpin/PropellerCompiler/CompileSpin.h
Normal file
76
Tools/unix/OpenSpin/PropellerCompiler/CompileSpin.h
Normal file
@@ -0,0 +1,76 @@
|
||||
///////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// Propeller Spin/PASM Compiler Command Line Tool 'OpenSpin' //
|
||||
// (c)2012-2016 Parallax Inc. DBA Parallax Semiconductor. //
|
||||
// See end of file for terms of use. //
|
||||
// //
|
||||
///////////////////////////////////////////////////////////////
|
||||
//
|
||||
// CompileSpin.h
|
||||
//
|
||||
#ifndef _COMPILESPIN_H_
|
||||
#define _COMPILESPIN_H_
|
||||
|
||||
typedef char* (*LoadFileFunc)(const char* pFilename, int* pnLength, char** ppFilePath);
|
||||
typedef void (*FreeFileBufferFunc)(char* pBuffer);
|
||||
|
||||
struct CompilerConfig
|
||||
{
|
||||
CompilerConfig()
|
||||
: bVerbose(false)
|
||||
, bQuiet(false)
|
||||
, bFileTreeOutputOnly(false)
|
||||
, bFileListOutputOnly(false)
|
||||
, bDumpSymbols(false)
|
||||
, bUsePreprocessor(true)
|
||||
, bAlternatePreprocessorMode(false)
|
||||
, bUnusedMethodElimination(false)
|
||||
, bDocMode(false)
|
||||
, bDATonly(false)
|
||||
, bBinary(true)
|
||||
, eeprom_size(32768)
|
||||
{
|
||||
}
|
||||
|
||||
bool bVerbose;
|
||||
bool bQuiet;
|
||||
bool bFileTreeOutputOnly;
|
||||
bool bFileListOutputOnly;
|
||||
bool bDumpSymbols;
|
||||
bool bUsePreprocessor;
|
||||
bool bAlternatePreprocessorMode;
|
||||
bool bUnusedMethodElimination;
|
||||
bool bDocMode;
|
||||
bool bDATonly;
|
||||
bool bBinary;
|
||||
unsigned int eeprom_size;
|
||||
};
|
||||
|
||||
|
||||
void InitCompiler(CompilerConfig* pCompilerConfig, LoadFileFunc pLoadFileFunc, FreeFileBufferFunc pFreeFileBufferFunc);
|
||||
void SetDefine(const char* pName, const char* pValue);
|
||||
unsigned char* CompileSpin(char* pFilename, int* pnResultLength);
|
||||
void ShutdownCompiler();
|
||||
|
||||
#endif // _COMPILESPIN_H_
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// TERMS OF USE: MIT License //
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy of this //
|
||||
// software and associated documentation files (the "Software"), to deal in the Software //
|
||||
// without restriction, including without limitation the rights to use, copy, modify, //
|
||||
// merge, publish, distribute, sublicense, and/or sell copies of the Software, and to //
|
||||
// permit persons to whom the Software is furnished to do so, subject to the following //
|
||||
// conditions: //
|
||||
// //
|
||||
// The above copyright notice and this permission notice shall be included in all copies //
|
||||
// or substantial portions of the Software. //
|
||||
// //
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, //
|
||||
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A //
|
||||
// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT //
|
||||
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION //
|
||||
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE //
|
||||
// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. //
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
686
Tools/unix/OpenSpin/PropellerCompiler/CompileUtilities.cpp
Normal file
686
Tools/unix/OpenSpin/PropellerCompiler/CompileUtilities.cpp
Normal file
@@ -0,0 +1,686 @@
|
||||
//////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// Propeller Spin/PASM Compiler //
|
||||
// (c)2012-2016 Parallax Inc. DBA Parallax Semiconductor. //
|
||||
// Adapted from Chip Gracey's x86 asm code by Roy Eltham //
|
||||
// See end of file for terms of use. //
|
||||
// //
|
||||
//////////////////////////////////////////////////////////////
|
||||
//
|
||||
// CompileUtilities.cpp
|
||||
//
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
#include "Utilities.h"
|
||||
#include "PropellerCompilerInternal.h"
|
||||
#include "SymbolEngine.h"
|
||||
#include "Elementizer.h"
|
||||
#include "ErrorStrings.h"
|
||||
#include "CompileUtilities.h"
|
||||
|
||||
bool SkipBlock(int column)
|
||||
{
|
||||
int savedObjPtr = g_pCompilerData->obj_ptr;
|
||||
bool savedStringPatchEnable = g_pCompilerData->str_patch_enable;
|
||||
g_pCompilerData->str_patch_enable = false;
|
||||
if (!CompileBlock(column))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
g_pCompilerData->str_patch_enable = savedStringPatchEnable;
|
||||
g_pCompilerData->obj_ptr = savedObjPtr;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SkipRange()
|
||||
{
|
||||
int savedObjPtr = g_pCompilerData->obj_ptr;
|
||||
bool savedStringPatchEnable = g_pCompilerData->str_patch_enable;
|
||||
g_pCompilerData->str_patch_enable = false;
|
||||
bool bRange;
|
||||
if (!CompileRange(bRange))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
g_pCompilerData->str_patch_enable = savedStringPatchEnable;
|
||||
g_pCompilerData->obj_ptr = savedObjPtr;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SkipExpression()
|
||||
{
|
||||
int savedObjPtr = g_pCompilerData->obj_ptr;
|
||||
bool savedStringPatchEnable = g_pCompilerData->str_patch_enable;
|
||||
g_pCompilerData->str_patch_enable = false;
|
||||
if (!CompileExpression())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
g_pCompilerData->str_patch_enable = savedStringPatchEnable;
|
||||
g_pCompilerData->obj_ptr = savedObjPtr;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CheckIndex(bool& bIndex, int& expSourcePtr)
|
||||
{
|
||||
bIndex = false;
|
||||
if (g_pElementizer->CheckElement(type_leftb))
|
||||
{
|
||||
expSourcePtr = g_pElementizer->GetSourcePtr();
|
||||
if (!SkipExpression())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (!g_pElementizer->GetElement(type_rightb))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
bIndex = true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CheckIndexRange(bool& bIndex, int& expSourcePtr)
|
||||
{
|
||||
bIndex = false;
|
||||
if (g_pElementizer->CheckElement(type_leftb))
|
||||
{
|
||||
expSourcePtr = g_pElementizer->GetSourcePtr();
|
||||
if (!SkipExpression())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (g_pElementizer->CheckElement(type_dotdot))
|
||||
{
|
||||
if (!SkipExpression())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (!g_pElementizer->GetElement(type_rightb))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
bIndex = true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CheckVariable_AddressExpression(int& expSourcePtr)
|
||||
{
|
||||
bool bIndex = false;
|
||||
if (!CheckIndex(bIndex, expSourcePtr))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (!bIndex)
|
||||
{
|
||||
g_pCompilerData->error = true;
|
||||
g_pCompilerData->error_msg = g_pErrorStrings[error_eleftb];
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CheckVariable(bool& bVariable, unsigned char& type, unsigned char& size, int& address, int& indexSourcePtr)
|
||||
{
|
||||
address = g_pElementizer->GetValue();
|
||||
indexSourcePtr = 0;
|
||||
|
||||
unsigned char varType = (unsigned char)(g_pElementizer->GetType() & 0xFF);
|
||||
|
||||
if (varType >= type_var_byte && varType <= type_var_long)
|
||||
{
|
||||
type = type_var_byte;
|
||||
// adjust address base on the var size
|
||||
if (varType < type_var_long)
|
||||
{
|
||||
address += g_pCompilerData->var_long;
|
||||
}
|
||||
if (varType == type_var_byte)
|
||||
{
|
||||
address += g_pCompilerData->var_word;
|
||||
}
|
||||
}
|
||||
else if (varType >= type_dat_byte && varType <= type_dat_long)
|
||||
{
|
||||
type = type_dat_byte;
|
||||
}
|
||||
else if (varType >= type_loc_byte && varType <= type_loc_long)
|
||||
{
|
||||
type = type_loc_byte;
|
||||
}
|
||||
else
|
||||
{
|
||||
type = varType;
|
||||
if (varType == type_size)
|
||||
{
|
||||
size = (unsigned char)(g_pElementizer->GetValue() & 0xFF);
|
||||
if (!CheckVariable_AddressExpression(address))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
bool bIndex = false;
|
||||
if (!CheckIndex(bIndex, indexSourcePtr))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
bVariable = true;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
size = 2;
|
||||
if (varType == type_spr)
|
||||
{
|
||||
if (!CheckVariable_AddressExpression(address))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
bVariable = true;
|
||||
return true;
|
||||
}
|
||||
else if (varType == type_reg)
|
||||
{
|
||||
bool bIndex = false;
|
||||
if (!CheckIndexRange(bIndex, indexSourcePtr))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (bIndex)
|
||||
{
|
||||
size = 3;
|
||||
}
|
||||
bVariable = true;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
bVariable = false;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
// if we got here then it's a var/dat/loc type
|
||||
// set size
|
||||
size = varType;
|
||||
size -= type;
|
||||
bool bIndex = false;
|
||||
if (!CheckIndex(bIndex, indexSourcePtr))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (!bIndex)
|
||||
{
|
||||
// check for .byte/word/long{[index]}
|
||||
if (g_pElementizer->CheckElement(type_dot))
|
||||
{
|
||||
bool bEof = false;
|
||||
if (!g_pElementizer->GetNext(bEof)) // get byte/word/long
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (g_pElementizer->GetType() != type_size)
|
||||
{
|
||||
g_pCompilerData->error = true;
|
||||
g_pCompilerData->error_msg = g_pErrorStrings[error_ebwol];
|
||||
return false;
|
||||
}
|
||||
if (size < (g_pElementizer->GetValue() & 0xFF)) // new size must be same or smaller
|
||||
{
|
||||
g_pCompilerData->error = true;
|
||||
g_pCompilerData->error_msg = g_pErrorStrings[error_sombs];
|
||||
return false;
|
||||
}
|
||||
size = (g_pElementizer->GetValue() & 0xFF); // update size
|
||||
|
||||
bool bIndexCheck = false;
|
||||
if (!CheckIndex(bIndexCheck, indexSourcePtr))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
bVariable = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GetVariable(unsigned char& type, unsigned char& size, int& address, int& indexSourcePtr)
|
||||
{
|
||||
bool bEof = false;
|
||||
if (!g_pElementizer->GetNext(bEof))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
bool bVariable = false;
|
||||
if (!CheckVariable(bVariable, type, size, address, indexSourcePtr))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (!bVariable)
|
||||
{
|
||||
g_pCompilerData->error = true;
|
||||
g_pCompilerData->error_msg = g_pErrorStrings[error_eav];
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CompileVariable(unsigned char vOperation, unsigned char vOperator, unsigned char type, unsigned char size, int address, int indexSourcePtr)
|
||||
{
|
||||
// compile and index(s)
|
||||
if (type != type_reg)
|
||||
{
|
||||
if (type == type_spr || type == type_size)
|
||||
{
|
||||
if (!CompileOutOfSequenceExpression(address))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (type != type_spr)
|
||||
{
|
||||
if (indexSourcePtr != 0)
|
||||
{
|
||||
if (!CompileOutOfSequenceExpression(indexSourcePtr))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unsigned char byteCode = 0;
|
||||
|
||||
if (type == type_spr)
|
||||
{
|
||||
byteCode = 0x24 | vOperation;
|
||||
}
|
||||
else if (type == type_reg)
|
||||
{
|
||||
byteCode = 0x3F;
|
||||
if (size != 2)
|
||||
{
|
||||
bool bRange = false;
|
||||
if (!CompileOutOfSequenceRange(indexSourcePtr, bRange))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (bRange)
|
||||
{
|
||||
byteCode = 0x3E;
|
||||
}
|
||||
else
|
||||
{
|
||||
byteCode = 0x3D;
|
||||
}
|
||||
}
|
||||
if (!EnterObj(byteCode))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
// byteCode = 1 in high bit, bottom 2 bits of vOperation in next two bits, then bottom 5 bits of address
|
||||
byteCode = 0x80 | ((vOperation & 3) << 5) | (address & 0x1F);
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((type != type_var_byte && type != type_loc_byte) || size != 2 || address >= 8*4 || indexSourcePtr != 0)
|
||||
{
|
||||
// not compact
|
||||
byteCode = 0x80 | (size << 5);
|
||||
if (indexSourcePtr != 0)
|
||||
{
|
||||
byteCode |= 0x10;
|
||||
}
|
||||
byteCode |= vOperation;
|
||||
if (type != type_size)
|
||||
{
|
||||
if (type == type_dat_byte)
|
||||
{
|
||||
byteCode += 4;
|
||||
}
|
||||
else if (type == type_var_byte)
|
||||
{
|
||||
byteCode += 8;
|
||||
}
|
||||
else if (type == type_loc_byte)
|
||||
{
|
||||
byteCode += 12;
|
||||
}
|
||||
else
|
||||
{
|
||||
g_pCompilerData->error = true;
|
||||
g_pCompilerData->error_msg = g_pErrorStrings[error_internal];
|
||||
return false;
|
||||
}
|
||||
if (!EnterObj(byteCode))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (address > 0x7F)
|
||||
{
|
||||
// two byte address
|
||||
byteCode = (unsigned char)(address >> 8) | 0x80;
|
||||
if (!EnterObj(byteCode))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
byteCode = (unsigned char)address;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// compact
|
||||
byteCode = (type == type_var_byte) ? 0x40 : 0x60;
|
||||
byteCode |= (unsigned char)address;
|
||||
byteCode |= vOperation;
|
||||
}
|
||||
}
|
||||
|
||||
if (!EnterObj(byteCode))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (vOperation == 2) // if assign
|
||||
{
|
||||
if (!EnterObj(vOperator))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CompileVariable_Assign(unsigned char vOperator, unsigned char type, unsigned char size, int address, int indexSourcePtr)
|
||||
{
|
||||
return CompileVariable(2, vOperator, type, size, address, indexSourcePtr);
|
||||
}
|
||||
|
||||
bool CompileVariable_Expression(unsigned char vOperator, unsigned char type, unsigned char size, int address, int indexSourcePtr)
|
||||
{
|
||||
if (!CompileExpression())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return CompileVariable(2, vOperator, type, size, address, indexSourcePtr);
|
||||
}
|
||||
|
||||
bool CompileVariable_PreSignExtendOrRandom(unsigned char vOperator)
|
||||
{
|
||||
unsigned char varType = 0;
|
||||
unsigned char varSize = 0;
|
||||
int varAddress = 0;
|
||||
int varIndexSourcePtr = 0;
|
||||
if (!GetVariable(varType, varSize, varAddress, varIndexSourcePtr))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return CompileVariable_Assign(vOperator, varType, varSize, varAddress, varIndexSourcePtr);
|
||||
}
|
||||
|
||||
bool CompileVariable_IncOrDec(unsigned char vOperator, unsigned char type, unsigned char size, int address, int indexSourcePtr)
|
||||
{
|
||||
return CompileVariable(2, vOperator | (((size + 1) & 3) << 1), type, size, address, indexSourcePtr);
|
||||
}
|
||||
|
||||
bool CompileVariable_PreIncOrDec(unsigned char vOperator)
|
||||
{
|
||||
unsigned char varType = 0;
|
||||
unsigned char varSize = 0;
|
||||
int varAddress = 0;
|
||||
int varIndexSourcePtr = 0;
|
||||
if (!GetVariable(varType, varSize, varAddress, varIndexSourcePtr))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return CompileVariable_IncOrDec(vOperator, varType, varSize, varAddress, varIndexSourcePtr);
|
||||
}
|
||||
|
||||
bool CompileParameters(int numParameters)
|
||||
{
|
||||
if (numParameters > 0)
|
||||
{
|
||||
if (!g_pElementizer->GetElement(type_left)) // (
|
||||
{
|
||||
return false;
|
||||
}
|
||||
for (int i = 0; i < numParameters; i++)
|
||||
{
|
||||
if (!CompileExpression())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (i < (numParameters - 1))
|
||||
{
|
||||
if (!g_pElementizer->GetElement(type_comma))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!g_pElementizer->GetElement(type_right)) // )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CompileConstant(int value)
|
||||
{
|
||||
if (value >= -1 && value <= 1)
|
||||
{
|
||||
// constant is -1, 0, or 1, so compiles to a single bytecode
|
||||
unsigned char byteCode = (unsigned char)(value+1) | 0x34;
|
||||
if (!EnterObj(byteCode))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// see if it's a mask
|
||||
// masks can be: only one bit on (e.g. 0x00008000),
|
||||
// all bits on except one (e.g. 0xFFFF7FFF),
|
||||
// all bits on up to a bit then all zeros (e.g. 0x0000FFFF),
|
||||
// or all bits off up to a bit then all ones (e.g. 0xFFFF0000)
|
||||
for (unsigned char i = 0; i < 128; i++)
|
||||
{
|
||||
int testVal = 2;
|
||||
testVal <<= (i & 0x1F); // mask i, so that we only actually shift 0 to 31
|
||||
|
||||
if (i & 0x20) // i in range 32 to 63 or 96 to 127
|
||||
{
|
||||
testVal--;
|
||||
}
|
||||
if (i& 0x40) // i in range 64 to 127
|
||||
{
|
||||
testVal = ~testVal;
|
||||
}
|
||||
|
||||
if (testVal == value)
|
||||
{
|
||||
if (!EnterObj(0x37)) // (constant mask)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (!EnterObj(i))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// handle constants with upper 2 or 3 bytes being 0xFFs, using 'not'
|
||||
if ((value & 0xFFFFFF00) == 0xFFFFFF00)
|
||||
{
|
||||
// one byte constant using 'not'
|
||||
if (!EnterObj(0x38))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
unsigned char byteCode = (unsigned char)(value & 0xFF);
|
||||
if (!EnterObj(~byteCode))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (!EnterObj(0xE7)) // (bitwise bot)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
else if ((value & 0xFFFF0000) == 0xFFFF0000)
|
||||
{
|
||||
// two byte constant using 'not'
|
||||
if (!EnterObj(0x39))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
unsigned char byteCode = (unsigned char)((value >> 8) & 0xFF);
|
||||
if (!EnterObj(~byteCode))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
byteCode = (unsigned char)(value & 0xFF);
|
||||
if (!EnterObj(~byteCode))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (!EnterObj(0xE7)) // (bitwise bot)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// 1 to 4 byte constant
|
||||
unsigned char size = 1;
|
||||
if (value & 0xFF000000)
|
||||
{
|
||||
size = 4;
|
||||
}
|
||||
else if (value & 0x00FF0000)
|
||||
{
|
||||
size = 3;
|
||||
}
|
||||
else if (value & 0x0000FF00)
|
||||
{
|
||||
size = 2;
|
||||
}
|
||||
unsigned char byteCode = 0x37 + size; // (constant 1..4 bytes)
|
||||
if (!EnterObj(byteCode))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
for (unsigned char i = size; i > 0; i--)
|
||||
{
|
||||
byteCode = (unsigned char)((value >> ((i - 1) * 8)) & 0xFF);
|
||||
if (!EnterObj(byteCode))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CompileOutOfSequenceExpression(int sourcePtr)
|
||||
{
|
||||
int savedSourcePtr = g_pElementizer->GetSourcePtr();
|
||||
g_pElementizer->SetSourcePtr(sourcePtr);
|
||||
if (!CompileExpression())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
g_pElementizer->SetSourcePtr(savedSourcePtr);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CompileOutOfSequenceRange(int sourcePtr, bool& bRange)
|
||||
{
|
||||
int savedSourcePtr = g_pElementizer->GetSourcePtr();
|
||||
g_pElementizer->SetSourcePtr(sourcePtr);
|
||||
if (!CompileRange(bRange))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
g_pElementizer->SetSourcePtr(savedSourcePtr);
|
||||
return true;
|
||||
}
|
||||
|
||||
// compiles either a value or a range and sets the bRange flag accordingly
|
||||
bool CompileRange(bool& bRange)
|
||||
{
|
||||
if (!CompileExpression())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (g_pElementizer->CheckElement(type_dotdot))
|
||||
{
|
||||
if (!CompileExpression())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
bRange = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
bRange = false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Compile relative address
|
||||
bool CompileAddress(int address)
|
||||
{
|
||||
address -= g_pCompilerData->obj_ptr; // make relative address
|
||||
address--; // compensate for single-byte
|
||||
|
||||
if ((address < 0 && abs(address) <= 64) || (address >= 0 && address < 64))
|
||||
{
|
||||
// single byte, enter
|
||||
address &= 0x007F;
|
||||
}
|
||||
else
|
||||
{
|
||||
// double byte, compensate and enter
|
||||
address--;
|
||||
if (!EnterObj((unsigned char)((address >> 8) | 0x80)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
address &= 0x00FF;
|
||||
}
|
||||
|
||||
return EnterObj((unsigned char)address);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// TERMS OF USE: MIT License //
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy of this //
|
||||
// software and associated documentation files (the "Software"), to deal in the Software //
|
||||
// without restriction, including without limitation the rights to use, copy, modify, //
|
||||
// merge, publish, distribute, sublicense, and/or sell copies of the Software, and to //
|
||||
// permit persons to whom the Software is furnished to do so, subject to the following //
|
||||
// conditions: //
|
||||
// //
|
||||
// The above copyright notice and this permission notice shall be included in all copies //
|
||||
// or substantial portions of the Software. //
|
||||
// //
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, //
|
||||
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A //
|
||||
// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT //
|
||||
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION //
|
||||
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE //
|
||||
// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. //
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user