1
0
mirror of https://github.com/cc65/cc65.git synced 2024-12-27 15:29:46 +00:00

Changed the PC-Engine's configuration file, so that the command line can build 8K, 16K, and 32K carts.

Adjusted the PCE's document, the start-up code, and the PCE library test makefile.  That makefile shows how to post-process the linker's output file.
This commit is contained in:
Greg King 2018-02-23 16:06:49 -05:00
parent 83890e56eb
commit 3a0506ccb3
5 changed files with 115 additions and 84 deletions

View File

@ -1,34 +1,29 @@
# linker config to produce simple NEC PC-Engine cartridge (.pce)
# linker config. to produce a NEC PC-Engine 8K, 16K, or 32K image (.bin)
SYMBOLS {
__CARTSIZE__: type = weak, value = $2000; # $2000, $4000, or $8000
__STACKSIZE__: type = weak, value = $0300; # 3 pages stack
}
MEMORY {
# FIXME: is this correct? the first 3? bytes cant be used?
ZP: file = "", start = $0003, size = $00FD, type = rw, define = yes;
# reset-bank and hardware vectors
ROM0: file = %O, start = $E000, size = $1FF6, fill = yes, define = yes;
ROMV: file = %O, start = $FFF6, size = $000A, fill = yes;
# first RAM page (also contains stack and zeropage)
RAM: file = "", start = $2200, size = $1e00, define = yes;
ZP: file = "", start = $0000, size = $0100, define = yes;
# RAM bank
MAIN: file = "", start = $2200, size = $1E00 - __STACKSIZE__, define = yes;
# ROM banks, before swapping, and after mapping
ROM: file = %O, start = $10000 - __CARTSIZE__, size = __CARTSIZE__, fill = yes, fillval = $FF;
}
SEGMENTS {
ZEROPAGE: load = ZP, type = zp, define = yes;
EXTZP: load = ZP, type = zp, define = yes, optional = yes;
APPZP: load = ZP, type = zp, define = yes, optional = yes;
STARTUP: load = ROM0, type = ro, define = yes;
ONCE: load = ROM0, type = ro, optional = yes;
CODE: load = ROM0, type = ro, define = yes;
RODATA: load = ROM0, type = ro, define = yes;
DATA: load = ROM0, run = RAM, type = rw, define = yes;
BSS: load = RAM, type = bss, define = yes;
VECTORS: load = ROMV, type = rw, define = yes;
ZEROPAGE: load = ZP, type = zp;
EXTZP: load = ZP, type = zp, optional = yes;
APPZP: load = ZP, type = zp, optional = yes;
DATA: load = ROM, run = MAIN, type = rw, define = yes;
INIT: load = MAIN, type = bss, optional = yes;
BSS: load = MAIN, type = bss, define = yes;
RODATA: load = ROM, type = ro;
CODE: load = ROM, type = ro;
LOWCODE: load = ROM, type = ro, optional = yes;
ONCE: load = ROM, type = ro, optional = yes;
STARTUP: load = ROM, type = ro, start = $FFF6 - $0066;
VECTORS: load = ROM, type = ro, start = $FFF6;
}
FEATURES {
CONDES: type = constructor,
label = __CONSTRUCTOR_TABLE__,

View File

@ -3,9 +3,9 @@
<article>
<title>PC-Engine (TurboGrafx) System specific information for cc65
<author>
<url url="mailto:groepaz@gmx.net" name="Groepaz/Hitmen">
<date>2016-09-29
<author><url url="mailto:groepaz@gmx.net" name="Groepaz/Hitmen">,<newline>
<url url="mailto:greg.king5@verizon.net" name="Greg King">
<date>2018-02-12
<abstract>
An overview over the PCE runtime system as it is implemented for the
@ -30,11 +30,36 @@ more than one platform. Please see the function reference for more
information.
<sect>Binary format<p>
The standard binary output format generated by the linker for the PCE target
is a cartridge image with no header. It is of course possible to change this
behaviour by using a modified startup file and linker config.
The binary output file generated by the linker, for the PCE target, is an
image, with no header, that has 8K bytes in the wrong place. That file must be
post-processed; the 8K at the end must be moved to the front of the image.
On POSIX systems, the <tt/dd/ command and the shell give a convenient way to do
it. Here is an example of their use:
<tscreen><verb>
dd if=conio.bin bs=8K skip=3 > conio.pce
dd if=conio.bin bs=8K count=3 >> conio.pce
</verb></tscreen>
The first command grabs the last 8K of a 32K file, and writes it as the first
part of a new file. The second command reads all but the last part of the old
file, and appends it to the new file.
<tscreen><verb>
+--------+--------+--------+--------+
| Bank 1 | Bank 2 | Bank 3 | Bank 0 | &lt;-- "conio.bin"
+--------+--------+--------+--------+
+--------+--------+--------+--------+
| Bank 0 | Bank 1 | Bank 2 | Bank 3 | &lt;-- "conio.pce"
+--------+--------+--------+--------+
</verb></tscreen>
<em/Note/: That <tt/.pce/ file shows the format of the ROM cartridge that is
plugged into a PC-Engine. But, that <tt/.bin/ file shows what programs
actually see when they execute the code in that cartridge.
<sect>Memory layout<p>
@ -52,19 +77,23 @@ Special locations:
<tag/Stack/
The C runtime stack is located in system RAM at &dollar;3FFF and growing downwards.
<tag/BSS and Data/
The BSS (uninitialized variables) and Data (initialized variables) sections are
placed one after the other into system RAM at &dollar;2000.
<tag/Data and BSS/
The Data (initialized variables) and BSS (uninitialized variables) sections are
placed one after the other into system RAM at &dollar;2200.
<tag/Heap/
The C heap is located after the end of the Data section and grows towards the C
The C heap is located after the end of the BSS section; and, grows towards the C
runtime stack.
<tag/Code/
The startup code is located at &dollar;E000 in the System/Hardware bank. Further
code can be placed in other ROM banks, this must be done manually however.
In an 8K ROM cartridge, code and read-only data are located between
&dollar;E000 and &dollar;FFF5 in the System bank.
In a 16K cartridge, code and read-only data are located between &dollar;C000
and &dollar;FFF5.
In a 32K cartridge, code and read-only data are located between &dollar;8000
and &dollar;FFF5.
</descrip><p>
@ -171,7 +200,8 @@ following functions (and a few others):
<sect>Other hints<p>
<itemize>
<item>a good emulator to use for PC-Engine is "mednafen" (<url url="http://mednafen.fobby.net/">)
<item><url url="https://mednafen.github.io/" name= "Mednafen"> is a good
emulator to use for the PC-Engine.
</itemize>
some useful resources on PCE coding:
@ -210,6 +240,3 @@ freely, subject to the following restrictions:
</enum>
</article>

View File

@ -4,33 +4,26 @@
; by Groepaz/Hitmen <groepaz@gmx.net>
; based on code by Ullrich von Bassewitz <uz@cc65.org>
;
; This must be the *first* file on the linker command line
; 2018-02-11, Greg King
;
.export _exit
.export __STARTUP__ : absolute = 1 ; Mark as startup
.import initlib, donelib
.import push0, _main, zerobss
.import initheap
.import push0, _main
.import IRQStub
; Linker generated
.import __RAM_START__, __RAM_SIZE__
.import __ROM0_START__, __ROM0_SIZE__
.import __ROM_START__, __ROM_SIZE__
.import __STARTUP_LOAD__,__STARTUP_RUN__, __STARTUP_SIZE__
.import __CODE_LOAD__,__CODE_RUN__, __CODE_SIZE__
.import __RODATA_LOAD__,__RODATA_RUN__, __RODATA_SIZE__
.import __DATA_LOAD__,__DATA_RUN__, __DATA_SIZE__
.import __BSS_SIZE__
; Linker-generated
.import __CARTSIZE__
.import __DATA_LOAD__, __DATA_RUN__, __DATA_SIZE__
.import __BSS_RUN__, __BSS_SIZE__
.import __MAIN_START__, __MAIN_SIZE__, __STACKSIZE__
.include "pce.inc"
.include "extzp.inc"
.importzp sp
.importzp ptr1,ptr2
.importzp tmp1,tmp2,tmp3
; ------------------------------------------------------------------------
; Place the startup code in a special segment.
@ -53,29 +46,27 @@ start:
ldx #$FF ; Stack top ($21FF)
txs
; At startup all MPRs are set to 0, so init them
lda #$ff
tam #%00000001 ; 0000-1FFF = Hardware page
; At power-on, most MPRs have random values; so, initiate them.
lda #$FF
tam #%00000001 ; $0000-$1FFF = Hardware bank
lda #$F8
tam #%00000010 ; 2000-3FFF = Work RAM
; FIXME: setup a larger block of memory to use with C-code
tam #%00000010 ; $2000-$3FFF = Work RAM
;lda #$F7
;tam #%00000100 ; 4000-5FFF = Save RAM
;lda #1
;tam #%00001000 ; 6000-7FFF Page 2
;lda #2
;tam #%00010000 ; 8000-9FFF Page 3
;lda #3
;tam #%00100000 ; A000-BFFF Page 4
;tam #%00000100 ; $4000-$47FF = 2K Battery-backed RAM
;lda #4
;tam #%01000000 ; C000-DFFF Page 5
;lda #0
;tam #%10000000 ; e000-fFFF hucard/syscard bank 0
;tam #%00001000 ; $6000-$7FFF
; Clear work RAM (2000-3FFF)
stz <$00
tii $2000, $2001, $1FFF
lda #$01
ldx #>$8000
cpx #>__CARTSIZE__
bcc @L1 ;(blt)
tam #%00010000 ; $8000-$9FFF = ROM bank 1 (32K block of ROM)
inc a
tam #%00100000 ; $A000-$BFFF = ROM bank 2
inc a
@L1: tam #%01000000 ; $C000-$DFFF = ROM bank 3 (32K) or 1 (16K)
;lda #$00 ; (The reset default)
;tam #%10000000 ; $E000-$FFFF hucard/syscard bank 0
; Initialize hardware
stz TIMER_CTRL ; Timer off
@ -91,15 +82,16 @@ start:
lda #$05
sta IRQ_MASK ; IRQ1=on
; Clear the BSS data
jsr zerobss
; Copy the .data segment to RAM
tii __DATA_LOAD__, __DATA_RUN__, __DATA_SIZE__
; Clear the .bss segment
stz __BSS_RUN__
tii __BSS_RUN__, __BSS_RUN__ + 1, __BSS_SIZE__ - 1
; Set up the stack
lda #<(__RAM_START__+__RAM_SIZE__)
ldx #>(__RAM_START__+__RAM_SIZE__)
lda #<(__MAIN_START__ + __MAIN_SIZE__ + __STACKSIZE__)
ldx #>(__MAIN_START__ + __MAIN_SIZE__ + __STACKSIZE__)
sta sp
stx sp + 1

View File

@ -1,12 +1,29 @@
.PHONY: all clean test
# Size of cartridge to generate.
# Possible values:
# 8K = 0x2000
# 16K = 0x4000
# 32K = 0x8000
CARTSIZE := 0x2000
ifeq (${CARTSIZE},0x8000)
COUNT := 3
else
COUNT := 1
endif
all: conio.pce
conio.pce: conio.c
../../../bin/cl65 -t pce conio.c --mapfile conio.map -o conio.pce
%.pce: %.bin
dd if=$< bs=8K skip=${COUNT} > $@
dd if=$< bs=8K count=${COUNT} >> $@
%.bin: %.c ../../../lib/pce.lib
../../../bin/cl65 -t pce $< -Wl -D__CARTSIZE__=${CARTSIZE} -m $*.map -o $@
clean:
$(RM) conio.o conio.pce conio.map
$(RM) conio.o conio.???
test: conio.pce
mednafen -force_module pce conio.pce
mednafen -force_module pce $<

View File

@ -45,7 +45,7 @@ void main(void)
p[8],p[9],p[10],p[11],p[12],p[13],p[14],p[15]
);
}
memcpy(p, main, 0); /* test that a zero length doesn't copy 64K */
memcpy(p, main, i = 0); /* test that a zero length doesn't copy 64K */
gotoxy(0,ysize - 1);
for (i = 0; i < xsize; ++i) {