Moderador: Sir Cilve Sinclair
saimazoom escribió:¿Hay alguna forma de saber lo que ocupa cada función en z88dk con el zcc?. El sdcc te muestra un mapa de memoria donde puedes ver lo que ocupa cada función. Gracias.
_loc_here = 7D9F, G: s1lk_1
_localidades_t = 9041, G: s1lk_2
_main = B2D8, G: s1lk_2
_mensajesSistema_t = 9244, G: s1lk_2
_mensajes_t = 9241, G: s1lk_2
_newLine = 8484, G: s1lk_1
_nombres_t = 930D, G: s1lk_2
_objectIsAttr = 7F8A, G: s1lk_1
saimazoom escribió:¿Cómo se lee el fichero map?. Parece que las funciones vienen precedidas de _, pero aparecen repetidas varias veces en el mapa y parecen estar ordenadas por orden alfabético (?). ¿Cómo calcular lo que ocupa una función en memoria?. Gracias.
asm_z80_push_di = $9683 ; G asm_z80_push_di
continue = $9687 ; L asm_z80_push_di
__code_compiler_head = $968E ; G
__code_lib_head = $968E ; G
__code_lib_tail = $968E ; G
__code_z80_tail = $968E ; G
;;;;;;;;;********** HERE IT IS
_getInput = $968E ; G eliza_c
l_getInput_00102 = $96B7 ; L eliza_c
;;;;;;;;*********** NEXT FUNCTION BELOW
_replace = $96C4 ; G eliza_c
l_replace_00113 = $96F1 ; L eliza_c
_getInput = $968E ; G eliza_c
677 0000 ;eliza.c:24: unsigned char* getInput()
678 0000 ; ---------------------------------
679 0000 ; Function getInput
680 0000 ; ---------------------------------
681 0000 _getInput:
682 0000 ;eliza.c:28: putchar('?');
683 0000 21 3F 00 ld hl,0x003f
684 0003 CD 00 00 call _putchar_fastcall
685 0006 ;eliza.c:29: putchar(' ');
686 0006 21 20 00 ld hl,0x0020
687 0009 CD 00 00 call _putchar_fastcall
688 000C ;eliza.c:31: if (!fgets(result, sizeof(result), stdin))
689 000C 11 00 00 ld de,_getInput_result_1_410+0
690 000F 4B ld c, e
691 0010 42 ld b, d
692 0011 2A 00 00 ld hl,(_stdin)
693 0014 D5 push de
694 0015 E5 push hl
695 0016 21 51 00 ld hl,0x0051
696 0019 E5 push hl
697 001A C5 push bc
698 001B CD 00 00 call _fgets_callee
699 001E D1 pop de
700 001F 7C ld a,h
701 0020 B5 or a,l
702 0021 20 06 jr NZ,l_getInput_00102
703 0023 ;eliza.c:32: exit(1);
704 0023 21 01 00 ld hl,0x0001
705 0026 CD 00 00 call _exit_fastcall
706 0029 l_getInput_00102:
707 0029 ;eliza.c:34: result[strlen(result) - 1] = '\0';
708 0029 6B ld l, e
709 002A 62 ld h, d
710 002B CD 00 00 call _strlen_fastcall
711 002E 2D dec l
712 002F 26 00 ld h,0x00
713 0031 19 add hl,de
714 0032 36 00 ld (hl),0x00
715 0034 ;eliza.c:35: return result;
716 0034 EB ex de,hl
717 0035 C9 ret
zcc +zx ..\libgfx\libgfx.c parser.c juego_compressed.c -o juego.bin -vn -O3 -startup=31 -lfzx -lfzxfonts_utz -m -lzx7
zcc +zx juego_pagina0_compressed.c -o juego_pagina0_.bin -vn -O3
#asm
include "juego.def"
#endasm
zcc +zx juego_pagina0_compressed.c -o juego_pagina0_compressed.bin -vn -O3
Key to filenames:
C:\Users\kmbr\AppData\Local\Temp\s7jc_.o = juego_pagina0_compressed.c
Error at module 's7jc_': symbol 'base_graphics' already defined in module 'zx82_crt0'
Error at module 's7jc_': symbol 'l_dcal' already defined in module 'zx82_crt0'
Error at module 's7jc_': symbol 'cleanup' already defined in module 'zx82_crt0'
saimazoom escribió:Estoy intentando separar en mi juego el código del motor y de las fases. La intención es paginar en 128Kb las fases pero manteniendo el motor por debajo de la 0xC000. He intentado lo siguente:
1) Primero compilo el motor
- Código: Seleccionar todo
zcc +zx ..\libgfx\libgfx.c parser.c juego_compressed.c -o juego.bin -vn -O3 -startup=31 -lfzx -lfzxfonts_utz -m -lzx7
There is some confusion here. "-startup=31" only works with the new C library in Z88DK and the new C library is only selected if "-clib=new", "-clib=sdcc_ix" or "-clib=sdcc_iy" appears on the compile line. In the new c library, "-startup=31" chooses start up code without any terminals attached to stdin, stdout, stderr which is what you usually want for games.
The new C library and the classic C library exist separately within z88dk. They each have their own start up code and their own library code. The new c library also contains FZX, ZX7 and all the FZX fonts (including UTZ's) already so it's not necessary to link or provide those separately. On the other hand, the classic library only has ZX7 and must be provided with the rest separately.
In the compile above you are using the classic C library and that does not define "-startup=31". I'm not sure how you are getting it to work without errors? The classic C library does not have an option to switch off terminals but the terminal code is also very small when they are not used.
-_printf_
+_printf
; a comment
+asm_
-[.]*
That said, let's compile with the classic library. The first step is you want to make a binary containing your engine only.
To do that:
zcc +zx --no-crt ..\libgfx\libgfx.c parser.c juego_compressed.c -o juego.bin -vn -O3 -lfzx -lfzxfonts_utz -lzx7 -gp -m
You will need a very recent version of z88dk to use "-gp" since this feature appeared after 1.99B. Either a nightly build or update via github. If you run "zcc -h" you should see "-g Generate a global defc file of the final executable (-g, -gp, -gpf filename)" in the listed options.
"--no-crt" means there will be no c start up code in the output. There will be no call to main() but also no initialization of variables. Since you are compiling into ram any variables you have defined should have their correct initial values. If you or the library needs to run initialization code, you will have to write a separate initialization function by either supplying a CRT or a separate routine to do so.
"-gp" will produce a special ".def" file with symbols. This one defines all your public symbols with exports ("PUBLIC foo ; defc foo = ...") that is ready for use in other compiles.
You won't want all those symbols exported. So you will want to specify which ones you want to keep. You can do that by supplying a "match file" that contains a list of regular expressions, one per line. zcc will match symbol names to that file to determine which ones you want in the .def file.
As an example, I will show you a simple "match.txt" file containing one regular expression per line:
"match.txt"
- Código: Seleccionar todo
-_printf_
+_printf
; a comment
+asm_
-[.]*
Lines beginning with "+" mean accept, "-" mean reject and ";" mean ignore.
The first two lines will accept the "_printf" symbol only. The fourth line will accept any symbols beginning with "asm" and the last line will reject everything else.
ZCC will go through those rules in order for each symbol and stop when it finds a match.
To use this rule file:
zcc +zx --no-crt ..\libgfx\libgfx.c parser.c juego_compressed.c -o juego.bin -vn -O3 -lfzx -lfzxfonts_utz -lzx7 -gpf match.txt -m
Now you will see the .def file is pruned down to only the symbols you want to export.
2) Luego intento compilar la fase, pero me devuelve el error de que no existe el símbolo de _main y el resto de símbolos de las funciones del motor.
- Código: Seleccionar todo
zcc +zx juego_pagina0_compressed.c -o juego_pagina0_.bin -vn -O3
I will not have time to fully describe SECTIONs tonight but I will briefly describe them and then give you an example of its use in the game Pietro Bros.
SECTIONs are containers into which the assembler places code and data. You specify which SECTION you want your code and data to be placed into and then in the linking step, you provide a memory map that tells the linker to what addresses those SECTIONs are mapped.
In a 128k game you might define SECTIONs for each 16k memory bank and then you can assign code and data to those sections.
Pietro Bros (source code) is using the new C library to compile. It specifies several options to the new C library's CRT in the file zpragma.inc
// DEFINE OWN MEMORY MAP
#pragma output __MMAP = -1 // memory map is provided in file "mmap.inc"
// COMPILE TIME CRT CONFIGURATION
#pragma output CRT_ORG_CODE = 23552 // org of compile
#pragma output REGISTER_SP = -1 // crt will not change stack location; loader sets sp
#pragma output CRT_ENABLE_CLOSE = 0 // don't bother closing files on exit
#pragma output CRT_ENABLE_EIDI = 0 // don't di on start or exit; loader does di before start
#pragma output CRT_ON_EXIT = 0 // jump to address 0 at exit
#pragma output CLIB_MALLOC_HEAP_SIZE = 0 // no malloc heap
#pragma output CLIB_STDIO_HEAP_SIZE = 0 // no stdio heap (no files)
#pragma output CLIB_FOPEN_MAX = -1 // no FILE* list
#pragma output CLIB_OPEN_MAX = -1 // no fd table
In particular "__MMAP = -1" tells the CRT that you will provide the memory map in the file mmap.inc. This is how Pietro Bros controls where everything is placed in memory.
"mmap.inc" is a modification of Z88DK's standard memory map. In Pietro Bro's "mmap.inc" file several new sections are defined:
* MCLOAD to place the initial loader code into the screen at address 16384
* LOADER to place the main loader code at address 23296
* BANK_06 to define a 128k memory bank at address 0xc000 to hold AY music and data
* NIRVANA_HOLE to place stuff in a hole left by the nirvana engine. The standard C memory map is modified to place the program's ram variables in that hole.
* CODE contains the program's main code at address 23552.
It's very easy to place ASM or C code and data into a specific section.
For ASM an example:
SECTION BANK_06
PUBLIC _myfunc
myfunc:
ld hl,10
ret
some_data:
defb 0,0,0
All of the above will be added to the BANK_06 section.
For C, you have to know that the compiler will place code and data into different sections: CODE (read only code), RODATA (read only data), DATA (self modifying code, variables not initially zero) and BSS (initially zero variables). Normally the section names it uses are "code_compiler", "rodata_compiler", "data_compiler" and "bss_compiler". The placement of these sections is defined in the standard memory map supplied by Z88DK.
You can change the sections that the compiler places those items into on a file granularity on the compile line using options "--codeseg CODE_NAME" "--constseg RODATA_NAME" "--dataseg DATA_NAME" "--bssseg BSS_NAME". For example, "--codeseg BANK_06 --constseg BANK_06" will put the C code and constant data into SECTION BANK_06.
zsdcc can only do the --codeseg and --constseg at this time but sccz80 can do all sections.
zcc +zx -c ..\libgfx\libgfx.c parser.c juego_compressed.c -o juego -vn -O3 --codeseg=ENGINE --constseg=ENGINE --dataseg=ENGINE --bssseg=ENGINE
z80nm juego.o | more
SECTION ENGINE
org 0xc000
defb 0
saimazoom escribió:Is working!. Today I was able to load the different pages and execute code from them and make callbacks to the engine. So far I'm using the first approach.
Nice to hear! I think you are probably the first person to actually do it this way. That "-gpf" feature was put in for this purpose but most bankswitching problems can be solved more simply with sections.
The "-gpf" thing is part of a stepping stone toward getting the toolchain to automatically generate bankswitched programs. The others are the command line options "--codeseg, --constseg, --dataseg, --bssseg" to have the compiler change section name (this is implemented for sccz80 and partially for sdcc) and to change sections within C source with pragmas (not done yet).
If you are interested in trying an sdcc compile, for the classic c library just add "-compiler=sdcc -SO3 --max-allocs-per-node200000 --reserve-regs-iy --fsigned-char" to the compile line. If you are using Windows or OSX, z88dk provides the zsdcc binary but others have to build zsdcc separately. The high optimization level (--max-allocs-per-node) will cause the compile to be very slow so if you have a large program don't be surprised if it takes 10-15 minutes. You may want to use "-v" instead of "-vn" so you can see what is going on. sdcc is particularly good if you use "unsigned char" variables where possible.
sdcc compilation with the classic library is just getting out of experimental so if you try it and it works, let me know. All these things were designed into the new c library from scratch so the classic is now catching up.
I'll like to give you credit in the game, Shall I use the forum nick?.
Volver a Programación y nuevos desarrollos
Usuarios navegando este Foro: No hay usuarios registrados visitando el Foro y 2 invitados