Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added cpct_loadBinaryFile and cpct_enableBackgroundROMs functions #132

Open
wants to merge 7 commits into
base: development
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
101 changes: 101 additions & 0 deletions cpctelera/src/firmware/cpct_enableBackgroundROMs.s
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
;;-----------------------------LICENSE NOTICE------------------------------------
;; This file is part of CPCtelera: An Amstrad CPC Game Engine
;; Copyright (C) 2021 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR)
;;
;; This program is free software: you can redistribute it and/or modify
;; it under the terms of the GNU Lesser General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.
;;
;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU Lesser General Public License for more details.
;;
;; You should have received a copy of the GNU Lesser General Public License
;; along with this program. If not, see <http://www.gnu.org/licenses/>.
;;-------------------------------------------------------------------------------

.module cpct_firmware

.include /firmware.s/
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; Function: cpct_enableBackgroundROMs
;;
;; Enables all background ROMs.
;;
;; C Definition:
;; void <cpct_enableBackgroundROMs> ()
;;
;; Assembly call:
;; > call cpct_enableBackgroundROMs_asm
;;
;; Requirements:
;; This function requires the CPC *firmware* to be *ENABLED*, as it uses
;; firmware routines to work.
;;
;; Details:
;; This function enables all background ROMs (i.e.: disc controller). When a
;; program is executed using Basic's *RUN* command, background ROMs are disabled.
;; In order to read data from disc, background ROMs must be enabled again. This
;; function achieves this by calling to firmware routines that reset the program
;; status (mc_start program) and enable background ROMs (kl_rom_walk).
;;
;; Those firmware routines reset the stack of the system, so it is very
;; important that cpct_enableBackgroundROMs is *called at the start of* '*main*'.
;; And, also important, '*main*' should *not have local variables*, as they
;; are stored in the stack. Be aware that some ROMs display messages on screen when
;; initialized, so you might need to clear the screen after calling this function.
;;
;; Known limitations:
;; * This function *will not work from ROM*, as it uses self-modifying code.
;;
;; Destroyed Register values:
;; AF, BC, DE, HL
;;
;; Required memory:
;; 30 bytes
;;
;; Time Measures:
;; Next table shows only time used by CPCtelera's code in cpct_enableBackgroundROMs. It does not
;; take into account time used by firmware functions mc_start_program and kl_rom_walk.
;; (start code)
;; Case | microSecs (us) | CPU Cycles
;; --------------------------------------
;; Any | 43 | 172
;; --------------------------------------
;; (end code)
;;
;; Credits:
;; This function was created based on code from Kevin Thacker.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

_cpct_enableBackgroundROMs::
cpct_enableBackgroundROMs_asm::

;; Save Return Address
pop hl ;; [3] HL = Return Address
ld (return_to_program+1), hl ;; [5] Save Return Adress in the code, as stack will be destroyed in firmware calls

;; store the drive number the loader was run from
ld hl,(#firmware_disc_mem_ptr) ;; [5] Read memory location of disc memory area. First byte is the current drive
ld a,(hl) ;; [2] Read current drive
ld (restore_drive+1),a ;; [4] Store current drive

;; Disable and reenable all background ROMs
ld c,#0xFF ;; [2] Disable all roms
ld hl, #continue_program ;; [3] Execution address for mc_start_program
jp firmware_mc_start_program ;; [3] Run a foreground program
continue_program:
call firmware_kl_rom_walk ;; [5] Enable all background ROMs

;; When AMSDOS is enabled, the drive reverts back to drive 0!
;; This will restore the drive number to the drive the program was run from
ld hl,(#firmware_disc_mem_ptr) ;; [5] Read memory location of current drive
restore_drive:
ld (hl),#0x00 ;; [3] Restore drive number to the drive the program was run from

;; Return to the caller of cpct_enableBackgroundROMs
return_to_program:
jp 0x0000 ;; [3] Return to caller
3 changes: 3 additions & 0 deletions cpctelera/src/firmware/firmware.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,4 +41,7 @@ extern void cpct_disableLowerROM();
extern void cpct_enableUpperROM();
extern void cpct_disableUpperROM();

// Background ROMs control
extern void cpct_enableBackgroundROMs();

#endif
34 changes: 29 additions & 5 deletions cpctelera/src/firmware/firmware.s
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,33 @@
;;
;; Constants used by firmware routines.
;;
;; firmware_RST_jp - Memory address that stores a pointer to the start of
;; firmware code, executed on every interruption.
;; GA_port_byte - Output port where Gate Array (GA) listens.
;; firmware_RST_jp - Memory address that stores a pointer to the start of firmware code,
;; executed on every interruption.
;; firmware_disc_mem_ptr - Memory address that stores a pointer to the start of the memory area
;; used by disc ROM.
;; GA_port_byte - Output port where Gate Array (GA) listens.
;;
.equ firmware_RST_jp, 0x38 ;; Memory address were a jump (jp) to the firmware code is stored.
.equ GA_port_byte, 0x7F ;; 8-bit Port of the Gate Array
;;
;;
;; Constants: Firmware jumpblock calls
;;
;; Memory adresses of some firmware functions.
;;
;; firmware_cas_in_open - Opens an input buffer and reads the first block of a file.
;; firmware_cas_in_direct - Reads an entire file directly into memory.
;; firmware_cas_in_close - Closes an input file.
;; firmware_mc_start_program - Run a foreground program.
;; firmware_kl_rom_walk - Enable all background ROMs.
;;
;;

.equ firmware_RST_jp, 0x38 ;; Memory address were a jump (jp) to the firmware code is stored.
.equ firmware_disc_mem_ptr, 0xBE7D ;; Memory address storing a pointer to disc ROM memory area.
.equ GA_port_byte, 0x7F ;; 8-bit Port of the Gate Array.


.equ firmware_cas_in_open, 0xBC77 ;; Opens an input buffer and reads the first block of a file.
.equ firmware_cas_in_direct, 0xBC83 ;; Reads an entire file directly into memory.
.equ firmware_cas_in_close, 0xBC7A ;; Closes an input file.
.equ firmware_mc_start_program, 0xBD16 ;; Run a foreground program.
.equ firmware_kl_rom_walk, 0xBCCB ;; Enable all background ROMs.
165 changes: 165 additions & 0 deletions cpctelera/src/loaders/cpct_loadBinaryFile.asm
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
;-----------------------------LICENSE NOTICE------------------------------------
;; This file is part of CPCtelera: An Amstrad CPC Game Engine
;; Copyright (C) 2021 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR)
;;
;; This program is free software: you can redistribute it and/or modify
;; it under the terms of the GNU Lesser General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.
;;
;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU Lesser General Public License for more details.
;;
;; You should have received a copy of the GNU Lesser General Public License
;; along with this program. If not, see <http://www.gnu.org/licenses/>.
;;-------------------------------------------------------------------------------

.include "firmware/firmware.s"

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; Function: cpct_loadBinaryFile
;;
;; Loads a binary file to a given place in memory.
;;
;; C Definition:
;; <u8> <cpct_loadBinaryFile> (void* *mem_load*, void* *filename*) __z88dk_callee;
;;
;; Input Parameters (4 Bytes):
;; (2B DE) mem_load - Pointer to the place in memory where loader will start to copy
;; the loaded file
;; (2B HL) filename - Pointer to the null terminated string containing the filename
;;
;; Assembly call (Input parameters on registers):
;; > call cpct_loadBinaryFile
;;
;; Return value (Assembly calls, return L):
;; <u8> - (0) = successful loading (no error), (1) = error happened during loading
;;
;; Parameter Restrictions:
;; * *filename* must be a pointer to a string containing the name of the file
;; that will be loaded. This string must be zero terminated and must contain a valid
;; filename. It is programmers responsibility to give correct value.
;; * *mem_load* must be a pointer to the byte where loaded bytes will start
;; to be copied to. Bytes will be copied from *mem_load* onwards into memory.
;; There is no restriction on were this pointer can point to, but it is
;; programmer's responsibility to ensure that loaded bytes will not overwrite
;; any important data in memory. This function does not do any check in this sense.
;;
;; Requirements:
;; This function requires the CPC *firmware* to be *ENABLED*, as it uses
;; firmware routines to load data. Also, for loading a file from disc, it
;; requires *background ROMs* to be *ENABLED*.
;;
;; Known limitations:
;; * This function does not do any kind of boundary or size checking. If you
;; give an incorrect value for *filename* or your *mem_load* pointer is placed wrong,
;; undefined behaviour will happen. This will probably make your programs hang
;; or crash.
;;
;; Details:
;; This function loads a binary file to a given place in memory (*mem_load*),
;; using firmare routines. In order to read a file from disc, it is necessary that
;; background ROMs are activated. However, when a program is loaded using Basic's
;; command *run* "*program*", background ROMs are disabled. Therefore, for loading
;; files from disc, background ROMs must be enabled again before using this function.
;; That can be achieved using *cpct_enableBackgroundROMs*.
;;
;; If background ROMs are not enabled (or when using a system without disc drive),
;; cpct_loadBinaryFile will load files from tape. In this case a 2K buffer (placed at
;; 0xC000) will be used. Also, loading messages will be displayed on screen. It is
;; recommended to use *cpct_miniload* for tape loading.
;;
;; If there are failures during loading, the routine returns with an error code (1).
;; When loading has no errors, it returns (0).
;;
;; Use example:
;; (start code)
;; // This example will load a sprite from disc using firmware functions.
;; // For this example an image has been previously converted to sprite, in bin format,
;; // and placed the resulting file "cpct.bin" into the DSK folder of the project.
;; #include <cpctelera.h>
;; void programcontrol(void) {
;; // Declare a pointer to video memory
;; u8* pvmem;
;; // Clear the screen, as some ROMs print messages on screen when activated
;; cpct_clearScreen(0);
;; // Make pvmem point to the byte where we want to print a sprite
;; pvmem = cpct_getScreenPtr(CPCT_VMEM_START, 25, 50);
;; // Load a file named "cpct.bin" into memory address 0x5000
;; cpct_loadBinaryFile((void *)0x5000,"cpct.bin");
;; // Draw the actual sprite (where pvmem is pointing)
;; cpct_drawSprite((void *)0x5000,pvmem, 30, 21);
;; // Loop forever
;; while (1);
;; }
;; // main function doesn't use local variables
;; void main(void) {
;; // cpct_enableBackgroundROMs is the first call in main, enables disc ROM
;; cpct_enableBackgroundROMs();
;; // Jump to central part of the program
;; programcontrol();
;; }
;; (end code)
;;
;; Destroyed Register values:
;; AF, BC, DE, HL, IX
;;
;; Required memory:
;; C-bindings - 41 bytes
;; ASM-bindings - 38 bytes
;;
;; Time Measures:
;; Next table shows only time used by CPCtelera's code in cpct_loadBinaryFile. It does not
;; take into account time used by firmware functions to actually read the file. The total
;; time to read a file will be much bigger.
;; (start code)
;; Case | microSecs (us) | CPU Cycles
;; ----------------------------------------------
;; Best | 74 | 296
;; ----------------------------------------------
;; Asm saving | -12 | -48
;; ----------------------------------------------
;; (end code)
;;
;; Credits:
;; This function was created based on code from Kevin Tacker, and some tutorials
;; from Mochilote.
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;


;; cpct_loadBinaryFile starts here
push de ;; [4] Save loading address
push hl ;; [4] Save string location

;; Get filename string length
ld b,#0 ;; [2] Reset counter
getStrLen_loop:
ld a,(hl) ;; [2] Load a char from filename string
or a ;; [1] Test if it's 0
jr z,getStrLen_exit ;; [2/3] If so, exit loop
inc b ;; [1] Increment counter
inc hl ;; [2] HL points to next char
jr getStrLen_loop ;; [3] Next char
getStrLen_exit: ;; B = Filename length

;; Read file using firmware routines
pop hl ;; [3] Restore string location
ld de,#0xC000 ;; [3] two K buffer (not used with cas_in_open when reading disc)
call firmware_cas_in_open ;; [5] Open file
pop hl ;; [3] Restore loading address
jr nc,lb_error ;; [2/3] Exit if an error was detected
call firmware_cas_in_direct ;; [5] Read file
jr nc,lb_error ;; [2/3] Exit if an error was detected
call firmware_cas_in_close ;; [5] Close file
jr nc,lb_error ;; [2/3] Exit if an error was detected

;; Exit from function
ld l,#0 ;; [2] L = 0 ==> No errors detected
ret ;; [3] Return to caller
lb_error:
ld l,#1 ;; [2] L = 1 ==> Error detected
ret ;; [3] Return to caller
25 changes: 25 additions & 0 deletions cpctelera/src/loaders/cpct_loadBinaryFile_asmbindings.s
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
;;-----------------------------LICENSE NOTICE------------------------------------
;; This file is part of CPCtelera: An Amstrad CPC Game Engine
;; Copyright (C) 2021 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR)
;;
;; This program is free software: you can redistribute it and/or modify
;; it under the terms of the GNU Lesser General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.
;;
;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU Lesser General Public License for more details.
;;
;; You should have received a copy of the GNU Lesser General Public License
;; along with this program. If not, see <http://www.gnu.org/licenses/>.
;;-------------------------------------------------------------------------------
.module cpct_loaders

;;
;; ASM bindings for <cpct_loadBinaryFile>
;;
cpct_loadBinaryFile_asm:: ;; Assembly entry point

.include /cpct_loadBinaryFile.asm/
31 changes: 31 additions & 0 deletions cpctelera/src/loaders/cpct_loadBinaryFile_cbindings.s
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
;;-----------------------------LICENSE NOTICE------------------------------------
;; This file is part of CPCtelera: An Amstrad CPC Game Engine
;; Copyright (C) 2021 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR)
;;
;; This program is free software: you can redistribute it and/or modify
;; it under the terms of the GNU Lesser General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.
;;
;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU Lesser General Public License for more details.
;;
;; You should have received a copy of the GNU Lesser General Public License
;; along with this program. If not, see <http://www.gnu.org/licenses/>.
;;-------------------------------------------------------------------------------
.module cpct_loaders

;;
;; C bindings for <cpct_loadBinaryFile>
;;
;; 12 us, 3 bytes
;;
_cpct_loadBinaryFile::
pop hl ;; [3] HL = Return Address
pop de ;; [3] DE = Loadind Address
ex (sp),hl ;; [6] HL = Filename, and put return address in the stack again
;; as this function uses __z88dk_callee convention

.include /cpct_loadBinaryFile.asm/
3 changes: 3 additions & 0 deletions cpctelera/src/loaders/loaders.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,5 +24,8 @@
// Cassette loader in miniload format
u8 cpct_miniload(void* mem_load, u16 size) __z88dk_callee;

// Binary file loader using firmware
extern u8 cpct_loadBinaryFile(void *loadAddr, const char* fileName) __z88dk_callee;

#endif