org 00f0h
db 00,05
dw fillen
db 00,00,00,00,00,00,00,00,00,00,00,00
startpr
(code)
fillen equ $-startpr
And after "feeding" Nick with values from the LPT, that memory can be used for other stuff, right?
And after "feeding" Nick with values from the LPT, that memory can be used for other stuff, right?No, Nick continously reading it. But you can page out, and page in other memory segment for the Z80 if your program need a lot of memory.
the source code what Zozo linked (also used for converted speccy programs) to you is better than that what you could see on this document.
What do you think about rename your first topic as "EP assembly for beginers" or something? And can continue talking about sample.asm or any other questions about how to begin.I think it'd be not a bad idea:).
I am not sure though what happens if an LPB is for multiple scanlines: is the LPB re-read anyway on each scanline, or not?It is re-read on every line.
What can happen if I do an OUT to a non-existent port?I think nothing happens and you can do it, but if you substitute with CP (HL) and CP H it is also 2 bytes, and 11 clock cycles.
Can I replace it with, for example, OUT (0x00),A?
1. How do I wait for the vertical retrace?Put the interrupt request the previous LPB of Vertical retrace LPB, the interrupt will occure at retrace LPB.
2. How can I turn off the OS? (or is it actually a bad idea?) The system calls complicate the code somewhat...and I have a feeling that the majority of games have it turned off (like the Amstrad's firmware on the CPC)...You do not need to turn off it, it is enough to page out it, and make an own interrupt routine, do not forget to set the right latch and divider bits of port 0b4h in the interrupt ,in case of video interrupt:
ld a,30h
out (0b4h),a
If it is not done, then the interrupt flag is not deleted, and the machine remains interrupt request loop.3. Why in all (three) example codes I've seen, the interrupts are disabled somewhere at the beginning of the program and never turned on later in the code (implicitly).I do not know, it is not necessary to turn off it, the stack pointer has to be set.
And two not strictly-programming-related questions:Unfortunately there is no PC tracker, only tracker on EP.
1. Where can I find a tracker (preferably a PC one...) for enterprise's sound chip?
2. Where can I find a palette reference for the enterprise? (I saw the formula for the colors in the docs and generated the palette to see, but maybe there's a table with possible gradients and stuff (maybe some example 16-color palettes to see how the bias system works visually, what constraints does it pose)?)
It is re-read on every line.
2. How can I turn off the OS? (or is it actually a bad idea?)It is very bad idea write EXOS incompatible program!
To Geco:I thought that the flag register is not important, it will be modified later :oops:
There are some Z80 instructions lasting 11 time cycles, the lenght is not so important as this is new code, but unfortunately all of them can affect the flags or capital registers inside some nested loops.
Also a 7 cycles instruction plus a NOP doesn`t suits.
I think I will try the inexistent port OUT instruction or try to change previously the value of register A....18 times.
Thanks..
All of these are included in the sample.asm! You need just write the main code! (http://enterpriseforever.com/Smileys/phpbb/ds_icon_smile.gif)..and that's why it is harder for me to read it... But I guess I shouldn't worry too much about the setup part and just get to the main code...
If you can specify which memory paging, and which video mode needed for you then I can modify the sample for your requirements!Thanks, but I actually managed to get those code samples I've written for those blocky modes to work within the sample.asm.
(...) don't use EXOS during the running, use it only for file I/O, and memory allocation. EXOS IRQ routine can be replaced (placing jump to 38h) but it is needed to restored before EXOS calls used (for example load next level in the game), or exit program.As for replacing the interrupt handler... will this be enough (as a dummy interrupt)?:
;; set interrupt
ld a,&c3 ; c3 = jp opcode
ld hl,Interrupt
ld (&0038),a
ld (&0039),hl
;; ...
;; and later...
.Interrupt:
di
ld a,30h
out (0b4h),a
ei
ret
.FrameFlyB
ld b,&f5
.FFBLoop
in a,(c)
rra
jr nc,FFBLoop
ret
Unfortunately there is no PC tracker, only tracker on EP.I "checked" what I could find (not much)... Which is the most user friendly?
I do not know if it exists, but I can do a palette only for bias values if it is good for you.Thank you, but I don't want to waste your time. I should be able to do that on my own.
About ensuring exos compatibility... is this enough:As for replacing the interrupt handler... will this be enough (as a dummy interrupt)?:Yes, and the DI inside the interrupt is not necessary.Code: [Select];; set interrupt
ld a,&c3 ; c3 = jp opcode
ld hl,Interrupt
ld (&0038),a
ld (&0039),hl
;; ...
;; and later...
.Interrupt:
di
ld a,30h
out (0b4h),a
ei
ret
I suppose it is a stupid question...but...You can do it with a simple HALT instruction if interrupt is not disabled or
I set up the virq in my LPT and now...how do I check for this video interrupt at the beginning of my program's mainloop?
I am looking for a equivalent of amstrad's:Code: [Select].FrameFlyB
ld b,&f5
.FFBLoop
in a,(c)
rra
jr nc,FFBLoop
ret
chk50hz in a,(0b4h)
bit 4,a
jr z,chk50hz
@gecoI "checked" what I could find (not much)... Which is the most user friendly?Music box is the most user friendly, but if I remember well you are not able to use all effects ( may be I have wrong )
"Music Box" has a lot of example tunes to load...but how do I do that in the emulator? I use the fileIO but I get an "drive A" error... Thank you, but I don't want to waste your time. I should be able to do that on my own.
You can do it with a simple HALT instruction if interrupt is not disabled orOh, I thought that the z80 in interrupt mode 1 triggers six interrupts per frame.. :oops:(300Hz)...but that seems to be true only for the amstrad? Just read that on the spectrum
is triggered at the start of the vertical blank period of the screen refresh. This cannot be changed
You can do it with a simple HALT...Actually the first thing I tried earlier was a halt...but then it didn't work...Commented some code and now it works...:oops:
Is there a z80 crossassembler for use with Context that uses Maxam's assembler syntax (used by WinApe cpc emulator)?I used WinApe assembler once or twice, and if I remember well with a small modification of source you can translate the code with SJASM.
I'm writing because I have a problem with LPT generation... Say I want to have L (1<=L<=288) lines high and C chars wide, vertically centered display - how to code the border and vblank lines so it will work properly?...Do you want a separate LPT lines for each pixel lines, or a shortest LPT (then two lines needed for the max 288 lines, plus the sync block)?
I have roblems with the sync block.As I remember, the sysnc block should be left untouched, you can put an LPB line before sync block, and there the number of lines can be varied as you want.
I have roblems with the sync block.My sync block from the IVIEW, can be used up to 301 lines screen.
; PIXEL for 256 lines (4 color)
DB 256-256,pixel+c4+vres,14,14+32
DW screen,0
DB 0,1,2,3,4,5,6,7
;blank for 5 lines ; bottom margin
DB 256-5,lpixel,63,0
DB 0,0,0,0,0,0,0,0,0,0,0,0
;black for 10 lines ; start of vertical blanking period
DB 256-10,lpixel,4,63
DB 0,0,0,0,0,0,0,0,0,0,0,0
;start vsync (4 lines) ; vertical sync pulse
DB 256-4,vblank,4,63
DB 0,0,0,0,0,0,0,0,0,0,0,0
;end vsync (1 line) ; finish vertical sync pulse
DB 256-1,vblank,63,4
DB 0,0,0,0,0,0,0,0,0,0,0,0
;black for 30 lines
DB 256-30,lpixel,4,63 ; rest of vertical blanking period
DB 0,0,0,0,0,0,0,0,0,0,0,0
;blank for 6 lines ; top margin with reload to satart again
DB 256-6,reload+lpixel,63,0
DB 0,0,0,0,0,0,0,0,0,0,0,0
What is the role of left/right margin in the sync lines?It determines where the VSYNC begins and ends within a line. When the video mode for a line is 0, then borders are blank (always black, regardless of the border color), and the active area is VSYNC (negative level relative to black). Without interlace, it should start at the beginning of a line, and the standard length is 2.5 lines, although it is not a problem if it is slightly longer. There are normally 3 blank lines before the VSYNC, and also a few after it. The additional black lines in the EXOS manual are the rest of the vertical retrace period, this area is also what TV broadcast uses for teletext.
Should I have the com file just be a loader for the "real" code? (I think most games have a small com and at least one prg file...)
Could someone explain how this should be done properly?:oops:
Yes, using a small .com file and a large .prg file is a common solution.How do I write a loader?:oops:
Alternatively, if not using multiple files is important, you can increase the size of the .com file up to about 63 KB, and then use epcompress (http://enterpriseforever.com/programozas/fajltomorites-enterprise-on/msg31929/#msg31929) to reduce it to the standard maximum of 47.75 KB or below so that EXOS can load it. The -m3 algorithm is the least efficient compression, but it should be good enough for this purpose, and it is the fastest to unpack and has the lowest memory usage, so it leaves the most space for the program.
How do I write a loader?:oops:Here is a small loader example:
macro exos n
rst 030h
defb n
endm
org 00f0h
db 00,05
dw fillen
db 00,00,00,00,00,00,00,00,00,00,00,00
startpr ld sp,0100h
ld a,0ffh
out (0b2h),a ;system segment to page2
ld hl,error
ld (0bff8h),hl ;store soft reset in EXOS segment
call seg ;ask a free segment from EXOS
out (0b3h),a
xor a ;open channel 0, and load file header of prg
ld de,prg
exos 1
jp nz,error ;jp error if error occured
ld de,0c000h ;load file to 0c000h, length 4000h
ld bc,4000h
exos 6
jp nz,error ;jp error if error occured
xor a
exos 3 ;close channel 0
jp prgstart
prg db 8,"data.prg" ;length of file name, file name
seg exos 24 ;ask a free 16k page
jp nz,error ;if not enough memory, then reset
ld a,c
ret
error di ;soft reset routin
ld sp,0100h
ld a,0ffh
out (0b2h),a
ld c,40h
exos 0
ld a,01h
out (0b3h), a
ld a,06h
jp 0c00dh
fillen equ $-startpr
jp nz,error ;jp hiba if error occured
Hungarian label left in the comment :oops: How do I write a loader?:oops:
For instance, the margin examples I've posted a while back. They have code in $0100-$0800, but the screens start at $8000 and $c000, then the LPT is placed in $f000-$f94f, so it won't run from basic (and in through debugger I have to initially load it twice to the memory). If I wanted to keep this layout I would have to compress the gfx, keep the lpt in another place in memory and later unpack the gfx and copy the lpt where I wanted it to be, right (or just skip compression and just copy the data from lower memory to where I want...)?:oops:
Hungarian label left in the comment :oops:
Large unused memory areas that are filled with zeros are compressed to only a few bytes. After the original program is unpacked in memory, it is run as usual starting at 100h.
Also, the 'szeg' label has not been renamed to 'seg' where the routine is called.
When you load games from tape you can hear when loading lot of zeros. I really hate when I hear it for a minutes... :twisted: Ok, from SD card don't problem, just wasting of the storage space :-)Can you show me how it's sounds when a lot of zeros loaded from tape?
Can you show me how it's sounds when a lot of zeros loaded from tape?
And the CRC bytes add some rhythm :-):lol: :lol: :lol:
Is there a z80 crossassembler for use with Context that uses Maxam's assembler syntax (used by WinApe cpc emulator)?
WRITE "C:\Z80coding\PROGRAM.COM"
WRITE "C:\Z80coding\PROGRAM.COM"
READ "C:\Z80coding\PROGRAM.ASM"
... In other words, empty space filled with FFh loads faster from tape than zeros....This cannot be true. The bit time-slots of the Manchaster code is equidistant. And thus no matter what kind of bits coded inside two same-lenght file it's always has the same time lenght.
The actual whole cycle times and frequencies used for the two tape speeds are:
Fast Speed Slow Speed
leader cycle 424µs (2358 Hz) 1000µs (1000 Hz)
one bit 344µs (2907 Hz) 800µs (1250 Hz)
zero bit 504µs (1984 Hz) 1200µs ( 883 Hz)
sync bit 696µs (1437 Hz) 1600µs ( 625 Hz)
There is 48K 00h: 4:14It was interesting to hear the samples :)
And 48K FFh: 3:02
I get error after calling exos 1.What is the error code?
I've tried without a header, with a type 5 header and header copied from rick2 prg.Header don't needed for the data file.
What is the error code?A=$fe (I get "EXOS function call not allowed" - after calling exos 28 which supposedly translates the error number to message string)
Which configuration used for loading?You mean ep128emu configuration? ep128-exdos-fileio...
Header don't needed for the data file.ok
Are you edited the file name and length in the loader for your program?I had my prg test file named as in the example code - "data.prg".
A=$fe (I get "EXOS function call not allowed" - after calling exos 28 which supposedly translates the error number to message string):shock:
:shock:Well I just copy-pasted the example code into my assembler, prepared a small prg-to-be file with little code without start address.
Can you upload your program for can I see it in debugger?
- at the BASIC prompt press START (F1) for load the program, then select the .COM file
It seems that the system segment has to always be assigned to a page in memory.Only under the system operations. In your program can you page in anything to Page1-3. (on P0 normaly are the Page 0 segment, where the EXOS entry point and IRQ handler at the start.)
Only under the system operations. In your program can you page in anything to Page1-3. (on P0 normaly are the Page 0 segment, where the EXOS entry point and IRQ handler at the start.)
So in order to make use of the $ff segment with exos calls (for loading from file) I have to load all data to another segment and later move it to the $ff segment, right?
You wrote, you need 2 video segments. Then you should not use segment $FF but some other, so you won't have these problems (there is 64K video RAM so there are four 16K sized video segments: $FC, $FD, $FE, $FF). $FF is the system segment, so if you overwrite it, you probably won't be able to use any EXOS function, no keyboard handling (by EXOS) etc whatsoever, also warm reset won't work, etc.But it seems that the system segment must always be mapped... And so I can't really use any other video segment then...
The best way: use EXOS segment allocation call, thus you can be sure a segment is "yours". Unfortunately there is no EXOS call to allocate a _video_ segment. Common technique is to allocate segments (and remember them!) in a loop till you got enough video segments (segnum >= $FC) then free segments you don't need from the stored allocated ones created throughout the allocator loop.I'm actually doing something similar as I'm "basing" my code on geco's rick dangerous 2 loader.
Of course it's possible to "take over" the machine and use memory as you want, but then you may need to forget EXOS and you need to do everything at your own (direct hardware access). It can be painful if you need file access later too (especially because doing hardware level EXDOS card access won't work if the user has some other solution - like the SD card cartridge - where compatibility is provided at software level). But if you can pre-load anything before the "take over" it can be OK. Though on EP the "elegant" way that you don't need to "cold reset" the machine, the RAM disk is not cleared, etc, but it requires to keep system segment intact ...I think I'd prefer to do it the "elegant" way...
But it seems that the system segment must always be mapped... And so I can't really use any other video segment then...
When I don't map $ff then my screen doesn't render - seems that there're some problems with LPT processing...
No! Important rule: the Z80 as the CPU sees memory "through" the Dave memory segment mapper (ports B0-B3 to set). But Nick *always* see the video RAM (segments $FC-$FF) regardless what you map in for the CPU. So the address Nick address 0 (eg for LD1 pointer in some LPB) *always* means the 0th byte in segment $FC even if that segment is not mapped in for the CPU at all! In other words: Nick uses another memory layout scheme, and sees 64K at the end of the EP memory space (thus segments $FC-$FF) linearly and always. The segment mapping is for the CPU _only_!
Sorry, it's me again...If you use the video RAM request code from the loader then only 1 problem can be there, it saves the allocated segments into a place specified by HL, possibly this area is overwritten, and therefore EXOS 25 will not free up any page, so all of your segments remained in use therefore no free space for EXOS for loading.
How should "allocate segment and load data from a file into it" go?
If I use a segment allocation routine with exos 24 then I can't do exos 1 because I get insufficient memory.
All works when I don't do the allocation.
Using exos 25 for freeing the segments I won't need doesn't help.
I'm quite frustrated.
As you can see I don't really have a clue what I'm doing...
Sorry, it's me again...
How should "allocate segment and load data from a file into it" go?
If I use a segment allocation routine with exos 24 then I can't do exos 1 because I get insufficient memory.
All works when I don't do the allocation.
Using exos 25 for freeing the segments I won't need doesn't help.
I'm quite frustrated.
As you can see I don't really have a clue what I'm doing...
Thanks! That was my problem - I set the lpt pointer with the address as in my mapped memory instead of the "absolute" nick memory address...
Sorry for being stupid...
loader:
ld a,0ffh
out (0b2h),a
ld hl,resetRoutine
ld (0bff8h),hl
call allocateMemory
ld c,$ff ; free system segment
exos 25 ;
call load_screen1_segment_data
call load_screen2_segment_data
ret
load_screen1_segment_data:
ld a,(screen1_segment)
out ($b3),a
xor a
ld de,dat1prg
exos 1
jp nz,resetRoutine
ld de,0c000h
ld bc,9803
exos 6
jp nz,resetRoutine
xor a
exos 3
ret
load_screen2_segment_data:
ld a,(screen2_segment)
out ($b3),a
xor a
ld de,dat1prg
exos 1
jp nz,resetRoutine
ld de,0c000h
ld bc,14672
exos 6
jp nz,resetRoutine
xor a
exos 3
ret
dat0prg db 8,"dat0.prg"
dat1prg db 8,"dat1.prg"
resetRoutine
di ;soft reset routine
ld sp,0100h
ld a,0ffh
out (0b2h),a
ld c,40h
exos 0
ld a,01h
out (0b3h), a
ld a,06h
jp 0c00dh
allocateMemory
ld de,segment_table+1
ld hl,segment_table
ld (hl),0
ld bc,8
ldir
ei
ld hl,segment_table
am1
exos 24
add a,a
jr nz,am2
ld (hl),c
inc l
jr nz,am1
am2:
;-----------------------
; for 1st video buffer (in-game)
call getVideoSegment
jr nc,resetRoutine
ld (screen1_segment),a
; get 2nd video buffer segment (in-game)
call getVideoSegment
jr nc,resetRoutine
ld (screen2_segment),a
; get additional video buffer segment
call getVideoSegment
jr nc,resetRoutine
ld (additional_video_segment),a
;----
; free unused segments:
ld hl,segment_table
am111:
call free_segment
inc l
jr nz,am111
ret
free_segment
xor a
cp (hl)
ret z
ld c,(hl)
ld (hl),a
exos 25
ret
getVideoSegment:
; numer segmentu zwracany w A
ld a,$fb
ld hl,segment_table
gvs1:
cp (hl)
jr c,gvs2
inc l
jp nz,gvs1
ret
gvs2:
ld a,(hl)
ld (hl),0
ret
screen1_segment equ $7fe0
screen2_segment equ $7fe1
additional_video_segment equ $7fe2
additional_normal_segment equ $7fe3
sharesegment_sizes equ $7fe0
sharesegment_table equ $7ff0
segment_table equ $7ff0+8
If you use the video RAM request code from the loader then only 1 problem can be there, it saves the allocated segments into a place specified by HL, possibly this area is overwritten, and therefore EXOS 25 will not free up any page, so all of your segments remained in use therefore no free space for EXOS for loading.I checked and it isn't overwriting the segment_table area and really tries to free the unused segments (returns result 0 for each exos 25). But I had to free $ff to get no memory errors when opening channel and loading... Although I freed $fa and $fb earlier... But it's only a workaround...
Loader of Rick Dangerous is Istvanv's loader :), mine loaders are not so documented :)Sorry Istvan
I checked and it isn't overwriting the segment_table area and really tries to free the unused segments (returns result 0 for each exos 25). But I had to free $ff to get no memory errors when opening channel and loading... Although I freed $fa and $fb earlier... But it's only a workaround...
allocateMemory
ld de,segment_table+1
ld hl,segment_table
ld (hl),0
ld bc,00ffh
ldir
ei
ld hl,segment_table
am1
exos 24
ld (hl),c
inc hl
jr z,am1 ;exit when reach FF segment (EXOS 24 returns with 7fh in A and FF in C, and F is NZ)
am2:
;-----------------------
; for 1st video buffer (in-game)
ld hl,segment_table
call getVideoSegment
jr nc,resetRoutine
ld (screen1_segment),a
; get 2nd video buffer segment (in-game)
call getVideoSegment
jr nc,resetRoutine
ld (screen2_segment),a
; get additional video buffer segment
call getVideoSegment
jr nc,resetRoutine
ld (additional_video_segment),a
;----
; free unused segments:
ld hl,segment_table
am111:
call free_segment
inc l
jr nz,am111
ret
free_segment
xor a
cp (hl)
ret z
ld c,(hl)
ld (hl),a
exos 25
ret
getVideoSegment:
; numer segmentu zwracany w A
ld a,$fb
gvs1:
cp (hl)
jr c,gvs2
inc l
jp nz,gvs1
ret
gvs2:
ld a,(hl)
ld (hl),0
ret
screen1_segment equ $7fe0
screen2_segment equ $7fe1
additional_video_segment equ $7fe2
additional_normal_segment equ $7fe3
sharesegment_sizes equ $7fe0
sharesegment_table equ $7ff0
segment_table equ $7e00 ;number of max segments is 256
When I'm loading my main file and it takes about 3 segments of data, is it always:It is better to save the segment numbers if you plan to change the pages.
loading into $f8 -> switch page1 to $f9 -> fill it -> switch page1 to $fa -> load the rest
or should I save the segment numbers somewhere, because it could load my data into $fb instead of $fa for example?
It is better to save the segment numbers if you plan to change the pages.How do I get their numbers when I'm loading a single big file?
How do I get their numbers when I'm loading a single big file?If I remember well, of FFh segment 3FFCh contains the page number which originally loaded to B1h page, 3FFDh stores B2h, but if you loded more than 32Kb, then B1h will contain the page which should be at B2h, and on FFh segment 3FFCh contains the page which should be paged in to B1h.