Hello,
does anyone know what address to call in order to execute the RUN command in BASIC? The BASIC program is preloaded at address &170 and the context loaded at &A670. Preferable an address that works with all BASIC versions.
If you mean RUN binary program:
adr=&A670:CALL @adr
You can also SAVE"name.bin",b,start,long,auto-start
And later run"name.bin
Quote from: ZorrO on 23:36, 11 January 25If you mean RUN binary program:
CALL address
You can also SAVE"name.bin",b,start,long,auto-start
And later run"name.bin
No, I mean what's the entry point in the BASIC jump table for the tokenised RUN command. In order to make a call from assembler that runs the current stored BASIC program.
Maybe this helps:
https://github.com/Bread80/Amstrad-CPC-BASIC-Source/blob/main/LoadSaveRun.asm
It's address #EA78 in Basic ROM (6128 version), but I have no idea how to handle the optional line number parameter.
*EDIT* oh, yes, it works :)
10 print"Hello"
20 goto 10
then assemble...
org #4000
rst #10
dw #ea78
ret
then
CALL &4000
Hello
Hello
Hello
Hello
...
you can even ESC+ESC and return to the prompt.
Quote from: Prodatron on 01:34, 12 January 25Maybe this helps:
https://github.com/Bread80/Amstrad-CPC-BASIC-Source/blob/main/LoadSaveRun.asm
It's address #EA78 in Basic ROM (6128 version), but I have no idea how to handle the optional line number parameter.
*EDIT* oh, yes, it works :)
10 print"Hello"
20 goto 10
then assemble...
org #4000
rst #10
dw #ea78
ret
then
CALL &4000
Hello
Hello
Hello
Hello
...
you can even ESC+ESC and return to the prompt.
Great! That's what I was looking for. You saved me precious time debugging myself. Thank you!
Below is some code that starts from a "clean sheet" by initialising AMSDOS and other ROMs, loading a BASIC program, setting up a character matrix for BASIC to use, and finally, running the BASIC program. It will also detect which model of CPC is being used. :)
I've tested it on a few BASIC listings but I can't guarantee it will work with every BASIC program!
org &8000
;Initialise all ROMs, including AMSDOS
start:
call &bb57 ;Disable firmware text output to the screen
ld hl,(&be7d) ;Get address where drive number is stored
inc hl
inc hl
ld a,(hl) ;Get drive number (A = 0, B = 1)
push af ;Store drive number
ld de,&40 ;DE = first usable byte of RAM
ld hl,&abff ;HL = last usable byte of RAM
call &bccb ;Initialise all background ROMs
ld (last_byte_addr),hl ;Store the new last usable byte of RAM, after
;space has been reserved for AMSDOS and other
;ROMs
pop af ;Get drive number
ld hl,(&be7d) ;Get address where drive number is stored
ld (hl),a ;Set drive number for use by BASIC
call &bb54 ;Re-enable firmware text output to the screen
;Load the BASIC program
load_file:
ld hl,filename ;HL = filename address
ld de,&c000 ;DE = file buffer address
ld b,12 ;B = length of filename
call &bc77 ;Open the file; on exit, BC contains file
;length
ld hl,&170 ;BASIC program starts at &170
push hl ;Store start address of BASIC program
add hl,bc ;Calculate address of last byte of BASIC
dec hl ;program
ld (basic_prog_end_addr),hl ;Store it for use later
pop hl ;Get start address of BASIC program
call &bc83 ;Read the contents of the file
call &bc7a ;Close the file
;Set up a matrix table for characters 240-255 to be redefined
ld de,240 ;DE = first character in matrix table
ld hl,(last_byte_addr) ;HL = last usable byte of RAM by BASIC
ld bc,16*8 ;16 characters in table, 8 bytes for each
;character
sbc hl,bc ;Calculate value of HIMEM
push hl ;Store it
inc hl ;Start address of matrix table is the byte
;following HIMEM
call &bbab ;Initialise the matrix table
;Check which version of BASIC is being used
ld c,0 ;0 = BASIC ROM number
call &b90f ;Select the BASIC ROM
ld hl,(basic_prog_end_addr) ;Get end address of BASIC program
pop de ;Get value of HIMEM (now in DE)
ld bc,(last_byte_addr) ;BC = last usable byte of RAM
ld a,(&c002) ;Read the version number
and a ;Is it 0 (i.e. CPC464 BASIC)?
jr z,start_basic_program_cpc464
;BASIC 1.1 is being used
ld (&ae66),hl ;Store the end address of the BASIC program
ld (&ae68),hl ;four times
ld (&ae6a),hl
ld (&ae6c),hl
ex de,hl ;Now HL = value of HIMEM
ld (&ae5e),hl ;Store HIMEM
ld (&ae60),bc ;Store last usable byte of RAM
cp 1 ;Is a CPC664 being used (version 1)?
jp z,&ea7d ;Yes
jp &ea78 ;No, so run the BASIC program
;BASIC 1.0 is being used
start_basic_program_cpc464:
ld (&ae83),hl ;Store the end address of the BASIC program
ld (&ae85),hl ;four times
ld (&ae87),hl
ld (&ae89),hl
ex de,hl ;Now HL = value of HIMEM
ld (&ae7b),hl ;Store HIMEM
ld (&ae7d),bc ;Store last usable byte of RAM
jp &e9bd ;Run the BASIC program
filename:
db "PROGRAM .BAS"
basic_prog_end_addr:
dw 0
last_byte_addr: ;Store the address of the last usable byte of
dw 0 ;RAM by BASIC
Hmmm... I should probably also upload this to CPCWiki somewhere... ::)
Quote from: Nich on 22:04, 14 January 25Below is some code that starts from a "clean sheet" by initialising AMSDOS and other ROMs, loading a BASIC program, setting up a character matrix for BASIC to use, and finally, running the BASIC program. It will also detect which model of CPC is being used. :)
I've tested it on a few BASIC listings but I can't guarantee it will work with every BASIC program!
org &8000
;Initialise all ROMs, including AMSDOS
start:
call &bb57 ;Disable firmware text output to the screen
ld hl,(&be7d) ;Get address where drive number is stored
inc hl
inc hl
ld a,(hl) ;Get drive number (A = 0, B = 1)
push af ;Store drive number
ld de,&40 ;DE = first usable byte of RAM
ld hl,&abff ;HL = last usable byte of RAM
call &bccb ;Initialise all background ROMs
ld (last_byte_addr),hl ;Store the new last usable byte of RAM, after
;space has been reserved for AMSDOS and other
;ROMs
pop af ;Get drive number
ld hl,(&be7d) ;Get address where drive number is stored
ld (hl),a ;Set drive number for use by BASIC
call &bb54 ;Re-enable firmware text output to the screen
;Load the BASIC program
load_file:
ld hl,filename ;HL = filename address
ld de,&c000 ;DE = file buffer address
ld b,12 ;B = length of filename
call &bc77 ;Open the file; on exit, BC contains file
;length
ld hl,&170 ;BASIC program starts at &170
push hl ;Store start address of BASIC program
add hl,bc ;Calculate address of last byte of BASIC
dec hl ;program
ld (basic_prog_end_addr),hl ;Store it for use later
pop hl ;Get start address of BASIC program
call &bc83 ;Read the contents of the file
call &bc7a ;Close the file
;Set up a matrix table for characters 240-255 to be redefined
ld de,240 ;DE = first character in matrix table
ld hl,(last_byte_addr) ;HL = last usable byte of RAM by BASIC
ld bc,16*8 ;16 characters in table, 8 bytes for each
;character
sbc hl,bc ;Calculate value of HIMEM
push hl ;Store it
inc hl ;Start address of matrix table is the byte
;following HIMEM
call &bbab ;Initialise the matrix table
;Check which version of BASIC is being used
ld c,0 ;0 = BASIC ROM number
call &b90f ;Select the BASIC ROM
ld hl,(basic_prog_end_addr) ;Get end address of BASIC program
pop de ;Get value of HIMEM (now in DE)
ld bc,(last_byte_addr) ;BC = last usable byte of RAM
ld a,(&c002) ;Read the version number
and a ;Is it 0 (i.e. CPC464 BASIC)?
jr z,start_basic_program_cpc464
;BASIC 1.1 is being used
ld (&ae66),hl ;Store the end address of the BASIC program
ld (&ae68),hl ;four times
ld (&ae6a),hl
ld (&ae6c),hl
ex de,hl ;Now HL = value of HIMEM
ld (&ae5e),hl ;Store HIMEM
ld (&ae60),bc ;Store last usable byte of RAM
cp 1 ;Is a CPC664 being used (version 1)?
jp z,&ea7d ;Yes
jp &ea78 ;No, so run the BASIC program
;BASIC 1.0 is being used
start_basic_program_cpc464:
ld (&ae83),hl ;Store the end address of the BASIC program
ld (&ae85),hl ;four times
ld (&ae87),hl
ld (&ae89),hl
ex de,hl ;Now HL = value of HIMEM
ld (&ae7b),hl ;Store HIMEM
ld (&ae7d),bc ;Store last usable byte of RAM
jp &e9bd ;Run the BASIC program
filename:
db "PROGRAM .BAS"
basic_prog_end_addr:
dw 0
last_byte_addr: ;Store the address of the last usable byte of
dw 0 ;RAM by BASIC
Hmmm... I should probably also upload this to CPCWiki somewhere... ::)
thanks for that brilliantly commented code!
..i dont know if ill use it... but i like it! :P