From 4f56609c8b1f938d45cade2425f5d315481212e1 Mon Sep 17 00:00:00 2001 From: ifilot Date: Sat, 15 Jul 2023 20:04:39 +0200 Subject: [PATCH] Automatic recognition of memory capacity of P2000T --- CHANGELOG.md | 51 +++++++++++++++ Makefile | 2 +- README.md | 4 +- src/build.py | 22 ++++++- src/ollie.asm | 175 ++++++++++++++++++++++++++++++-------------------- 5 files changed, 180 insertions(+), 74 deletions(-) create mode 100644 CHANGELOG.md diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..097125f --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,51 @@ +# Change Log +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](http://keepachangelog.com/) +and this project adheres to [Semantic Versioning](http://semver.org/). + +## [0.2.0] - 2023-07-15 + +### Added + +- Reading memory capacity of P2000T in source code and using that to automatically + determine the top part of RAM for transfer over RS232. + +### Changed + +### Fixed + +- Fixed error in memory address for the BASIC code for 32kb machines in the + README.md + +## [0.1.3] - 2023-07-14 + +### Added + +- Added instruction message on screen when executing `?USR1(0)` +- Adding software LICENSE + +### Changed + +### Fixed + +## [0.1.2] - 2023-07-14 + +### Added + +- Automatic compilation of ROM binary in release procedure + +### Changed + +### Fixed + +## [0.1.1] - 2023-07-14 + +### Added + +- Expanded upon documentation +- Adding CI/CD procecure + +### Changed + +### Fixed \ No newline at end of file diff --git a/Makefile b/Makefile index 90dc0f4..7e321f7 100644 --- a/Makefile +++ b/Makefile @@ -3,7 +3,7 @@ all: src/BASIC-MODIFIED.bin src/ollie.bin: src/ollie.asm z80asm src/ollie.asm -o src/ollie.bin -src/BASIC-MODIFIED.bin: src/ollie.bin +src/BASIC-MODIFIED.bin: src/ollie.bin src/build.py python3 src/build.py clean: diff --git a/README.md b/README.md index bf1e639..e19ebab 100644 --- a/README.md +++ b/README.md @@ -21,11 +21,11 @@ After booting the P2000T with the modified BASIC-NL image, run ```basic 10 CLEAR 50,&H9DFF -20 DEF USR1=&H4EC7 +20 DEF USR1=&H4EEE ``` > **Note**: Use `&H9DFF` in the above instructions if your P2000T has 16kb of memory. -> If your P2000T has 32kb or 48kb of memory, use `&HBDFF` or `&HDDFF`, respectively. +> If your P2000T has 32kb or 48kb of memory, use `&HDDFF` or `&HFDFF`, respectively. > Alternatively, you can also use the following one-liner to let the P2000T > figure it out for you: `10 CLEAR 50,&H9DFF+256*32*(PEEK(&H605C)+PEEK(&H605C)=1))`. diff --git a/src/build.py b/src/build.py index 0bd4937..5360933 100644 --- a/src/build.py +++ b/src/build.py @@ -3,11 +3,15 @@ import numpy as np import os import subprocess +import hashlib # set root path ROOT = os.path.dirname(__file__) +START = 0x3EC7 # start position on ROM def main(): + print('Building ROM...\n') + # open standard BASIC rom f = open(os.path.join(ROOT, 'BASICROM.BIN'), 'rb') rom = bytearray(f.read()) @@ -33,13 +37,25 @@ def main(): f = open(os.path.join(ROOT, 'ollie.bin'), 'rb') ollie = bytearray(f.read()) f.close() - rom[0x3EC7:0x3EC7+len(ollie)] = ollie + rom[START:START+len(ollie)] = ollie print("Inserting code; using %i / %i bytes of free space" % - (len(ollie),0x4000-0x3EC7)) + (len(ollie),0x4000-START)) - f = open(os.path.join(ROOT, 'BASIC-MODIFIED.bin'), 'wb') + # verify that the byte at 0x3EEE corresponds to the opt code for ld hl + print('Checking opt code at 0x3EEE=0x%02X ?= 0x21 (%s)' % + (rom[0x3EEE], 'true' if rom[0x3EEE]==0x21 else 'false')) + assert(rom[0x3EEE]==0x21) + + # store file + filename = os.path.join(ROOT, 'BASIC-MODIFIED.bin') + f = open(filename, 'wb') f.write(rom) f.close() + + # generate checksum + print() + print('Done writing modified ROM.') + print('Checksum: %s' % hashlib.md5(open(filename, 'rb').read()).hexdigest()) if __name__ == '__main__': main() \ No newline at end of file diff --git a/src/ollie.asm b/src/ollie.asm index a4012c5..3dd6581 100644 --- a/src/ollie.asm +++ b/src/ollie.asm @@ -1,14 +1,24 @@ ;------------------------------------------------------------------------------- -; This code is largely based on the source code as developed by +; This code is based on the source code as developed by ; dionoid(https://github.com/dionoid) as found via the link below: ; https://github.com/p2000t/software/blob/master/utilities/pc2p2000t/pc2p2000t.z80.asm ;------------------------------------------------------------------------------- -BasicProgStart: EQU $6547 -ProgramBlocks: EQU $9f4f ; byte -ProgramLength: EQU $9f34 ; word +basic_start_addr: EQU $6547 org $4ec7 +pageaddr: + DB $9f,$df,$ff ; set page address positions (upper byte) + +; exactly 27 bytes of data should be placed here such that the starting +; instruction is at $4eee; this allows for an easy BASIC command of +; `20 DEF USR1=&H4EEE` + + ; dummy data (36 bytes) + DB $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 + DB $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 + DB $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 + start: ld hl,.line1 ld de,$5000+20*$50 @@ -16,29 +26,27 @@ start: ld hl,.line2 ld de,$5000+21*$50 call printstring - ld hl,.line3 - ld de,$5000+22*$50 - call printstring jp read_program -.line1: DB "P2000T IS IN LISTENING MODE",255 -.line2: DB "COPY FILE OVER RS232",255 -.line3: DB "BAUD=9600, PARITY=N, DATA=8, STOP=1",255 +.line1: DB "P2000T READY TO COPY FILE OVER RS232",255 +.line2: DB "BAUD=9600, PARITY=N, DATA=8, STOP=1",255 +;------------------------------------------------------------------------------- ; reads a byte from the serial port (9600 baud) and returns in A +;------------------------------------------------------------------------------- read_byte: - push bc ; C5 [11] + push bc check_start_bit: - in a,($20) ; DB 20 [11] - and $01 ; E6 01 [7] - check if bit D0 is 0 - jr nz, check_start_bit ; 20 FA [7] - ld b, $15 ; 06 15 [7] + in a,($20) + and $01 ; check if bit D0 is 0 + jr nz, check_start_bit + ld b, $15 delay_on_start_bit: - djnz delay_on_start_bit ; 10 FE [13/8] - ld b, $08 ; 06 08 [7] + djnz delay_on_start_bit + ld b, $08 read_next_bit: - in a,($20) ; DB 20 [11] + in a,($20) ; 58 clocks without extra delay ; 1.2 * 1041.67 = 1250. Need delay in B: @@ -50,78 +58,109 @@ read_next_bit: ; 9600 baud: 1.2 * 260.42 = 312.5 ; delay in B: (312.5 - 58) / 13 = 19.6 + 1 = 21 (&h15) - rra ; 1F [4] - bit 0 into carry - rr c ; CB 19 [8] - push bc ; C5 [11] - ld b, $10 ; 06 10 [7] + rra ; bit 0 into carry + rr c + push bc + ld b, $10 delay_bit: - djnz delay_bit ; 10 FE [13/8] - pop bc ; C1 [10] - djnz read_next_bit ; 10 F3 [13] + djnz delay_bit + pop bc + djnz read_next_bit ; 72 clocks without extra delay. So delay in B: ; 2400 baud: (1041.67 - 72) / 13 = 74.6 + 1 = 76 (&h4C) ; 4800 baud: (520.84 - 72) / 13 = 34.53 + 1 = 35 (&h23) ; 9600 baud: (260.42 - 72) / 13 = 14.49 + 1 = 16 (&h10) - ld a,c ; 79 [4] - pop bc ; C1 [10] - ret ; C9 [10] + ld a,c + pop bc + ret +;------------------------------------------------------------------------------- +; read a program over the RS232 port +;------------------------------------------------------------------------------- read_program: ; start the program - di ; F3 - disable interrupts + di ; disable interrupts -read_header: ; read 256-byte header into $9f00 - $9fff - ld b,0 ; 06 00 - ld hl, $9f00 ; 21 00 9F +read_header: ; read 256-byte header into top of memory + call setpage + ld l,0 + ld b,0 read_header_loop: - call read_byte ; CD 00 9E - ld (hl),a ; 77 - inc hl ; 23 - djnz read_header_loop ; 10 F9 + call read_byte + ld (hl),a + inc hl + djnz read_header_loop ;read the blocks and put into basic memory - ld hl, ProgramBlocks ; 21 4F 9F - ld c, (hl) ; 4E - load number of blocks into C - ld hl, BasicProgStart ; 21 47 65 - IDEA: read pointer from $625c? - jr read_block ; 18 07 - first header already read, so skip + push bc + call setpage + pop bc + ld l,$4f ; set pointer to address containing number of blocks + ld c, (hl) ; load number of blocks into c + ld hl, basic_start_addr ; ?read pointer from $625c? + jr read_block ; first header already read, so skip ignore_header: - ld b, $00 ; 06 00 - ignore later 256-byte headers + ld b, $00 ; ignore later 256-byte headers ignore_header_loop: - call read_byte ; CD 00 9E - djnz ignore_header_loop ; 10 FB + call read_byte + djnz ignore_header_loop read_block: - ld de, $400 ; 11 00 04 + ld de, $400 read_block_loop: - call read_byte ; CD 00 9E - ld (hl),a ; 77 - inc hl ; 23 - dec de ; 1B - ld a,d ; 7A - or e ; B3 - jr nz, read_block_loop ; 20 F6 - dec c ; 0D - jr nz, ignore_header ; 20 E9 - - ld de, BasicProgStart ; 11 47 65 - ld hl, (ProgramLength) ; 2A 34 9F - add hl,de ; 19 - ld ($6405), hl ; 22 05 64 - set basic pointers to var space - ld ($6407), hl ; 22 07 64 - ld ($6409), hl ; 22 09 64 + call read_byte + ld (hl),a + inc hl + dec de + ld a,d + or e + jr nz, read_block_loop + dec c + jr nz, ignore_header + + ld de, basic_start_addr ; set de to start of basic program + call setpage ; set page in h + ld l,$34 + ld c,(hl) ; load lower byte program length + inc hl ; increment pointer + ld b,(hl) ; lower upper byte program length + ld a,b ; copy b->a->h + ld h,a + ld a,c ; copy c->a->l + ld l,a + add hl,de + ld ($6405), hl ; set basic pointers to var space + ld ($6407), hl + ld ($6409), hl ; reset the pointers to end of memory for BASIC - ld a, ($63b9) ; 3A B9 63 - add a, 2 ; C6 02 - ld ($63b9), a ; 32 B9 63 - ld ($6259), a ; 32 59 62 + ld a, ($63b9) + add a, 2 + ld ($63b9), a + ld ($6259), a ; succes: play beep - ld a,$07 ; 3E 07 - call $104a ; CD 4A 10 + ld a,$07 + call $104a - ei ; FB - enable interrupts - ret ; C9 + ei ; enable interrupts + ret + +;------------------------------------------------------------------------------- +; set the page to which the header data is written in h +; output: hl - start of buffer area +; uses: a,bc +;------------------------------------------------------------------------------- +setpage: + ld bc,pageaddr ; set pointer to page addresses + ld a,($605c) ; read RAM value, 1->16kb,2->32kb,3->48kb + dec a ; decrement such that index starts at 0 + add a,c ; add lower byte of page addr to it + ld c,a ; update lower byte page address pointer + ld a,(bc) ; load page byte into a + ld h,a ; set upper byte into h + ld l,$00 ; set lower byte to 0 + ret ;------------------------------------------------------------------------------- ; print string to screen