Systems - Development with NedoOS

Development with NedoOS 
Alone Coder 

 Under  NedoOS  can be developed on AC─ 
assembler, C, Pascal and Nedolang, but in this 
In this article I will tell you specifically about assembler. On 
there are most examples, and it will be with him 
It is more clear how the system works. 
In addition to examples,NedoOSprovides ra─ 
The employee has a large set of functions that 
usually too lazy to write from scratch, as well as the environment 
for automatic assembly. 

First acquaintance

   First acquaintance with the system for development─
The bot looks like this (if you have Windows):

 1. download everything from http://nedoos.ru/svn/ 
to a directory that does not contain spaces in the path 
2. enter this directory, or rather, in 
subdirectorysrc/ 
 3.runmkevo.bat.

   In this case, the entire system is rebuilt (to
at the time of writing this article - 70 packs─
Comrade), an SD card image is createdsd_nedo.vhd
(if it was not there), and it is written to
everything that is in release/.The image is in 
us/ - emulator directories. 
   How it works internally:

 1. mkevo.bat  writes settings files 
for ZX Evo configuration to filesrc/_sdk/ 
syssets.asm 
 2. mkevo.bat  runs make.bat with steam─ 
meter  noneedtrd  (that is, we don’t do trd- 
floppy disk image, we don't need it) 
 3. make.bat  creates if necessary 
directoryrelease/ 
 4. make.bat assembles the package fatfs4os (fa─ 
File system FAT) 
 5. make.bat  builds the package kernel (kernel 
OS), is creatednedoos.$c 
 6. make.bat  collects all packages in a loop 
by calling build.bat for each of them, and 
after building the package, copies it to release/ 
received  *.com, *.ext, *.txt,*.new  and 
subdirectory of the same name as the directory 
package 
 7. make.bat  if there is no parameter 
noneedtrd (and we have it) created─ 
it and fills test.trd 
 8. mkevo.bat renamesnedoos.$c to 
sd_boot.$c (so you can run from 
Evo Reset Servicewith one button 5) 
 9. mkevo.bat  launches chkimg.bat with pa─ 
meter sd (if there washdd,then they would work 
with a hard disk imagehdd_nedo.vhd ) 
 10. chkimg.bat creates if necessary 
image (using images.exe ) 
 11. chkimg.bat  writes everything to the image 
what is inrelease/ (using dmimg.exe ) 
 12. mkevo.bat launches the configured emu─ 
lator. 

 The collectors for the rest work similarly─
line configurations:

mkevsd-g.bat - ZX Evo without SD card in NeoGS 
mkatm3.bat - ATM3 on a floppy disk 
mkatm3hd.bat - ATM3 on HDD (Nemo IDE, possible 
fix in the batch file) 
mkatm3sd.bat - ATM3 onSD card 
mkpe26.bat - Pentagon 2.666LE on floppy disk 
mkpe26sd.bat - Pentagon 2.666LE on SD card 
mkatm2.bat - ATM2 on a floppy disk 
mkatm2hd.bat - ATM2 on HDD (ATM IDE) 

 They are all the same type, so everyone can
create your own collector or fix an existing one─
howling.
 makeall.bat  calls everything mk*.bat. It
must be run before committing to the reposito─
riy.

Batch file

   From all this (especially from the point about 
build.bat ) it is clear that the program is user─ 
it is better to write the body according to the existing ones
programs.  The easiest way is to take the directory 
emptyapp (or if your program is similar 
to some existing directory
toy), copy it entirely andcorrect.
   What does the simplest one look like build.bat:

 1. Setting up paths: 
if "%settedpath%"=="" call ../_sdk/ 
 setpath.bat
 2. Compilation (can be many lines, with 
calling the necessary resource conversion utilities and 
etc.): 
sjasmplus --nologo --msg=war emptyapp.asm 
This is where you can fix for 
your program, but if its main module 
is called emptyapp.asm - don't correct it :) 
 And the rest will most likely be corrected 
You won't have to do that. 

 3. If build.bat is called separately (from me─ 
nya this is the F9 button in Notepad++ ), thenкопиро─ 
вать в release/ и на образ SD-карты: 
if "%currentdir%"=="" ( 
FOR %%j IN (*.com) DO (
copy /Y %%j "../../release/bin/" > nul
"../../tools/dmimg.exe" ../../us/
             sd_nedo.vhd put %%j /bin/%%j
)
if "%makeall%"=="" ....usemul.exe 
) 
  Вариант  для игр с кучей файлов в одно─ 
имённой поддиректории: 
SET releasedir2=../../../release/ 
if "%currentdir%"=="" ( 
 FOR %%j IN (*.com) DO (
 "../../../tools/dmimg.exe" ../../../us/
        sd_nedo.vhd put %%j /nedogame/%%j
 move "*.com" "%releasedir2%nedogame">nul
 IF EXIST %%~nj xcopy /Y "%%~nj"
       "%releasedir2%nedogame%%~nj">nul
 )
cd../../../src/
call ..toolschkimg.bat sd
if "%makeall%"=="" ..usemul.exe 
) 
   Maybe someone can do it everywhere
the same? But for now we live like this.
   There is also a batch file option runcurl.bat,
which, after assembly, tries to transmit co─
abusive  *.com  via HTTP to an already running one
emulator, and then launch it remotely.
To do this, the emulator must be running
NedoOS, and it has a web server 3ws. 

Main module of the program

   Let's assume that you are writing a game. Its source─
the days are in src/games/somegame/. Her eyes─
The main module is called main.asm. Its com-
the file is called somegame.com, and add─
Line files are generated in  src/games/ 
somegame/somegame/  (during assembly they will end up in 
release/nedogame/somegame/somegame/ ). How 
looks main.asm:

 DEVICE ZXSPECTRUM128
 include "../../_sdk/sys_h.asm"
 ;all system constants and macros are there

STACK=0x4000 ;this is most convenient for games 

 org PROGSTART ;all programs start─
 ;can be found from this address 
begin 
 ld sp,STACK ;otherwise it will be sp=0 
;Our program does not work through stdio, but 
; she picks around the screen herself, so: 
 OS_HIDEFROMPARENT ;wake up the rod─
 ;program body (usually a navigator)
 ld e,0+128 ;e=0: EGA, e=2:MC,
  ;e=3: 6912, e=6: text
  ;+8=noturbo;+128=keep screen
                   ;e=-1: disable gfx
       OS_SETGFX ;включаем граф.режим и
      ;получаем фокус (out:e=old gfxmode)

       ld de,path
       OS_CHDIR ;входим в поддиректорию 
;...грузим файлы... 

mainloop 
;...играем... 
       jr mainloop

       ld hl,0 ;результат
       QUIT ;выход 
path 
       db "somegame",0

;...всякие процедурки, таблицы, инклюды... 

end 
savebin "somegame.com",begin,end-begin
LABELSLIST "../../../us/user.l" ;сохраним 
 ;метки,смотреть их дебагере Unreal Speccy
 If your program code compiles
several pages, then use direct─
tivu  PAGE and several savebin (you can under─
see in the projectbr,how this is done).

Debugging

   So if you wrote the above
example main.asm  and ran build.bat (not
forget to specify there main.asm ), then just
you will find yourself inUnreal Speccy.
 Click the button  "5"  you will find yourself in NedoOS,
run your game from there nedogame/
(you can automate this using 
autoexec.bat).PressShift+F1,to─ 
fall into the debugger. Press Ctrl+L,to
see the marks (and to unsee them - againCtrl+L ). 
 Make sure the current task is
your game: Tab (to the dump window), Ctrl+G,0080
- you should see somegame.com in the dump.
   If it's not, then go back to the window
disassembler  (Shift+Tab),  Ctrl+G, 0057
(end of interrupt handler), and then
press  F4 (execute to the cursor) until
you will seesomegame.comin the dump. Bottom right
currently enabled pages are visible in all
four quarters.
   Step through the program - F7. Step through the program─
starting calls - F8. Step to the exit along
stack - F11. You can rearrange the current
execution address -Z.
 During program execution, you can manually─
correct registers (go to them -
Shift+Tab,mouse also works).You can even
correct the program.
   If other tasks (especially term.com )
interfere with tracing your program, they can─
but close: once in this task, rearrange
execution address on0.
 View screen - F9.
 Save a piece of memory - Alt+W (save─
appears in src/ ). Load -Alt+R.
 Exit the debugger - Shift+F1. Current─
For some reason this version of the emulator is awesome─
dit to sticking Shift, so you need to poke
again Shift. When exiting the debugger that─
Also turns off  Kempston mouse, it is necessary
capture by clicking on the emulator window.

Loading and saving files from the program

   If you only need to read some
something small, like shipping, you can just
sketch:
 ld de,filename ;"name.ext",0
OS_OPENHANDLE ;opened the file
 or a
 jr nz, error ;could not open
 push bc ;b=open file handle
 ld de,SAVEDATA ;address where to ship
 ld hl,SAVEDATAsz ;how many bytes
 OS_READHANDLE ;loaded
 pop bc ;b=open file handle
 OS_CLOSEHANDLE ;closed

   Saving is similar, only instead of 
OPENHANDLE  write  CREATEHANDLE, and instead 
READHANDLE - WRITEHANDLE. Sample can 
look inuntangle.
 But usually the data must be loaded in the country─
Tsy, these pages need to be highlighted!
   Initially, the OS allocates to each program
4 pages, the numbers of which can be found out─
res  OS_GETMAINPAGES  (get dehl=pages 
in 0000, 4000, 8000, c000 ). Best 
recognize them at the very beginning and remember them on─
example, like this:
OS_GETMAINPAGES ;dehl=pages in
  ;0000,4000,8000,c000
 ld a,e
ld (pgmain4000),a
 ld a,h
ld (pgmain8000),a
 ld a,l
ld (pgmainc000),a 
;and then there will be loading 

 And at the end of the program write convenient
procedures for including these pages:

setpgmain4000 
pgmain4000=$+1 
 ld a,0
 SETPG4000
 ret 
setpgmain8000 
pgmain8000=$+1 
 ld a,0
SETPG8000
 ret 
setpgmainc000 
pgmainc000=$+1 
 ld a,0
 SETPGC000
ret

   If your program always includes
screen at 4000 and 8000, then volume makes sense─
combine setpgmain4000 and setpgmain8000 into
one procedure setpgsmain40008000. And now─
turn on the current screen through the procedure 
setpgsscr40008000.You don’t have to write this with 
zero, and borrow the entire module  src/ 
games/sprexamp/mem.asm. 
   So, we need to load some fa─
ylov into pages. Let's take a universal pro─
procedure for loading one page from the same 
sprexamp: 

loadpage 
;orders a page and uploads a file there 
;(nameфайла в hl) 
;out: hl=после имени файла, a=pg 
       push hl
       OS_NEWPAGE
       pop hl
       ld a,e
       push af ;pg
       SETPGC000
       push hl
       ex de,hl
       OS_OPENHANDLE
       push bc
       ld de,0xc000 ;addr
       ld hl,0x4000 ;size
       OS_READHANDLE
       pop bc
       OS_CLOSEHANDLE
       pop hl
       ld b,1
       xor a
       cpir ;after 0
       pop af ;pg
       ret

   И будем её вызывать так:

       ld hl,texfilename
       call loadpage
       ld (pg0),a
call loadpage
ld (pg1),a
 call loadpage
ld (pgsfx),a
 call loadpage
ld (pgmusic),a
etc.
   Inbr this is generally done in a loop, but─
A measure of pages are placed in the table.

texfilename 
 db "pg0.bin",0
 db "pg1.bin",0
 db "sfx.bin",0
 db "music.bin",0

   It's easy to convertloadpageto loading from
arbitrary address, which can also be
take from texfilename (for example, before the name─
file).

Drawing on the screen

   There are two ways to draw - in visible
screen or with double buffering (one
we update the screen, another one is visible).
   For dynamic games it is best to use─
call the second option, otherwise it’s possible
Problems with flickering and disappearing sprites.
The main loop of a game running on two computers─
wounds, looks something like this (example from 
loadscr ): 

 ld a,(timer)
ld (oldtimer),a 
;main loop 
mainloop 
;display background/restore it under sprites 
;... I recommend taking it from sprexamp! 

;sprite output 
 call setpgsscr40008000 ;enabled
  ;screen pages
 ld iy,spaceship0
 ld e,50 ;e=x = -(sprmaxwid-1)..159
  ;(encoded as x+(sprmaxwid-1))
 ld c,50 ;c=y = -(sprmaxhgt-1)..199
 ;(encoded as is)
 call prspr

 call setpgsmain40008000 ;enabled
;program pages in 4000,8000, as it was

;finisheddraw 
 ld a,(timer)
 push af
 call changescrpg ;from now on
 ;(more precisely, with INT) we will see what we drew

;logic 
;called as many times as elapsed 
;interrupts! 
mainloop_uvwaittimer0 
 ld a,(timer) 
oldtimer=$+1 
 ld b,0
ld (oldtimer),a
 sub b
 ld b,a
 jr z,mainloop_uvwaittimer0 ;if
 ;there have been no interruptions yet, let's spin here 
;b=how many interrupts have passed 
mainloop_uvlogic0 
 push bc
 call logic ;write your logic here
 pop bc
djnzmainloop_uvlogic0

;waiting for the screen to physically switch! 
;we can start a new rendering only if 
;at least one time has passed since changescrpg 
;interrupt (possibly inside logic) 
 pop bc ;b=timer during changescrpg 
waitchangescr0 
 ld a,(timer)
cp b
jr z,waitchangescr0

 ld a,(curkey)
 cp key_esc
 jp nz,mainloop ;exit via esc/break

   To make the timer work,connect the module 
sprexamp/int.asm  and use  swapimer 
(enable/disable custom
interrupt handler) before and after va─
of our main loop. Please note
music is not played in this handler, for
there is a systemiccallOS_SETMUSIC,
which guarantees smooth playback,
even if your task is superseded by others
tasks!
   Procedure  prspr  take from sprexamp/ 
prspr.asm.If you have compiled sprites─ 
not in pages, but in separate files
then you can define them prsprqwid=0x100,
and before the first call prspr write to 
0x100  command  jp prsprqwid. Generally possible 
start writing a game with a fix about─
ekta  sprexamp. There are even two ready-made
engine - with background scrolling along two axes
(without scrolling the background is not reprinted) and with
scrolling vertically (background reprinting─
always happens). And by the first engine already
screwed controls and logic in style
platformer.

 Worth reading nedoos.txt,api_base.txt 
andsys_h.asm, to get an idea 
about other system functions. 

Share your thoughts about the article