News:

Printed Amstrad Addict magazine announced, check it out here!

Main Menu

Example Z80 assembly programs (was:ASM source code)

Started by arnoldemu, 08:59, 04 April 10

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

arnoldemu

Quote from: arnoldemu on 13:11, 20 November 10
And now the version without the firmware:

http://www.cpctech.org.uk/source/sixpix.asm

This does some manipulation of the screen pixels to draw and mask the chars.
This example also shows how you can write text to the screen *without* the firmware and using your own pixel data.

The Y char position was not calculated correctly in this code. This has now been fixed.
My games. My Games
My website with coding examples: Unofficial Amstrad WWW Resource

arnoldemu

#51
Updated source:

http://www.cpctech.org.uk/source/6pixpatch.asm


I mostly fixed cursor position.
But still some bugs here.
My games. My Games
My website with coding examples: Unofficial Amstrad WWW Resource

Devilmarkus

Why not 2 RSX commands?
|LOCATE,<1-53>,<1-lines>
|PRINT,"HELLO WORLD"

+ these:
|PEN,x
|PAPER,y
When you put your ear on a hot stove, you can smell how stupid you are ...

Amstrad CPC games in your webbrowser

JavaCPC Desktop Full Release

AMSDOS

This is perhaps a bit beyond me, though I was playing around with txt_write_char and noticed you were only using "A" with the character byte, cause with that routine H contains the physical column number and L holds the physical line number. When I was trying it out as a standard writing routine with 65 in A it doesn't seem to obey writing outside the zone 0-39 and 0-24 seems to be it's range.

I didn't think it was possible to go beyond the bounds using text based Co-ordinates, hence the article from the early Amstrad CPC464 User (which became ACU) I posted was treating the text as graphically based characters. Interesting I "TAG"ged while your program was running and it wrote using the standard character set across the screen.

But there's a lot of stuff going on in that program that I don't know!  ??? 

I remember having this whole fastwriting routine for the IBM which allowed me to write wherever onscreen using Text based co-ordinates. I don't recall there being anything standard about it, though it came in very useful because I was converting some 80x50 Text Mode games in TP for CP/M-86. In CP/M-86 while you could tell it to go into 80x50 Mode, CP/M-86 simply didn't know anything about 80x50 text mode and needed a separate routine which would allow it to happen. I'm guessing this is the sort of thing your trying out here.
* Using the old Amstrad Languages :D * And create my own ;)
* Incorporating the Firmware :P
* I also like to problem solve code in BASIC :)   * And type-in Type-Ins! :D

Home Computing Weekly Programs
Popular Computing Weekly Programs
Your Computer Programs
Updated Other Program Links on Profile Page (Update April 16/15 phew!)
Programs for Turbo Pascal 3

arnoldemu

Quote from: CP/M User on 08:52, 06 December 10
This is perhaps a bit beyond me, though I was playing around with txt_write_char and noticed you were only using "A" with the character byte, cause with that routine H contains the physical column number and L holds the physical line number. When I was trying it out as a standard writing routine with 65 in A it doesn't seem to obey writing outside the zone 0-39 and 0-24 seems to be it's range.

I didn't think it was possible to go beyond the bounds using text based Co-ordinates, hence the article from the early Amstrad CPC464 User (which became ACU) I posted was treating the text as graphically based characters. Interesting I "TAG"ged while your program was running and it wrote using the standard character set across the screen.

But there's a lot of stuff going on in that program that I don't know!  ??? 

I remember having this whole fastwriting routine for the IBM which allowed me to write wherever onscreen using Text based co-ordinates. I don't recall there being anything standard about it, though it came in very useful because I was converting some 80x50 Text Mode games in TP for CP/M-86. In CP/M-86 while you could tell it to go into 80x50 Mode, CP/M-86 simply didn't know anything about 80x50 text mode and needed a separate routine which would allow it to happen. I'm guessing this is the sort of thing your trying out here.
I think tag makes it use the graphics drawing functions?

I was thinking about the char ranges and thought that perhaps I needed to redefine the window size, or perhaps also "WIDTH" or similar. Then it may work.

Well, the aim of this initially was to draw a 6 pixel wide font. Then I wanted to extend it so it could be used from BASIC without using any | commands. So you could use normal BASIC commands to use it.

Also, the size of the screen could be changed and this new charset used if you wanted.
I was interested in how much work I would need to do with patching the firmware jumpblock for it to work.
My games. My Games
My website with coding examples: Unofficial Amstrad WWW Resource

AMSDOS

arnoldemu wrote:

I think tag makes it use the graphics drawing functions?

Yep, TAG allows the user to enter standard Text Character from a Graphic co-ordinates position.

I was thinking about the char ranges and thought that perhaps I needed to redefine the window size, or perhaps also "WIDTH" or similar. Then it may work.

I try some experimenting with WINDOW 1,53,1,25, perhaps the firmware equivalent may do something, though I dare say it's all based on that one WINDOW routine. WIDTH might do something though it appears to be. I had a look though the firmware guide which had some stuff re;ating to the cursor though didn't see anything relating to the size of the cursor, merely the ability of turning it on and switching it off and something relating to drawing and undrawing the cursor!  :-[   There seems to be a few routines relating to the position of the cursor, though it may have to restrict itself to those standard position guidelines.

Anyhow I'm suprised to see how far it's developed into what you've created!  :)


* Using the old Amstrad Languages :D * And create my own ;)
* Incorporating the Firmware :P
* I also like to problem solve code in BASIC :)   * And type-in Type-Ins! :D

Home Computing Weekly Programs
Popular Computing Weekly Programs
Your Computer Programs
Updated Other Program Links on Profile Page (Update April 16/15 phew!)
Programs for Turbo Pascal 3

AMSDOS

I hope no-one minds me posting this old dinosaur of a routine in here!  ???

org &4000

    .setup 
     LD A,1   ;; My crude routine for setting up Scr_Mode
     CALL &BC0E
     LD A,240  ;; Setup Symbol Table - A Holds Character value
     LD HL,ship1  ;; HL points to Symbol Data to Define to
     CALL &BBA8  ;; Firmware routine to Redefine Symbol Table.
     LD A,241
     LD HL,ship2
     CALL &BBA8
     LD A,242
     LD HL,ship3
     CALL &BBA8
     LD A,243
     LD HL,ship4
     CALL &BBA8
    .init
     ld hl,&140C  ;; Initial Position
     LD A,0   ;; Initial Direction
    .loop
     PUSH HL   ;; Start of Main Loop
     PUSH AF
     CALL &BB75  ;; TXT SET CURSOR
     POP AF
     PUSH AF
     ADD A,240  ;; graphic code
     CALL &BB5D  ;; Print
     LD BC,&0C00  ;; Start Short Delay
    .shtdel
     DEC BC   
     LD A,B
     OR C
     JR NZ,shtdel  ;; loop back if Non Zero
     POP AF
     POP HL   ;; only HL actually wanted
     PUSH HL
     PUSH AF   ;; the next call corrupts AF & HL
     CALL &BB75  ;; TXT SET CURSOR
     LD A,32   ;; code for space
     CALL &BB5D  ;; Print
     LD A,0   ;; code for up arrow
     CALL &BB1E  ;; KM TEST KEY
     JR Z,proa  ;; Jump if Key Up
     POP AF   ;; reclaim direction code
     POP HL   ;; ..and position
     CP 0   ;; Compare A with 0 - up?
     JR NZ,right  ;; Jump to check Right if Not
     DEC L   ;; Up a row
     JR newpos  ;; Jump to the next position
    .right
     CP 1   ;; Compare with 1 - right?
     JR NZ,down
     INC H   ;; Right one column
     JR newpos
    .down
     CP 2   ;; Down?
     JR NZ,left
     INC L   ;; Down a row
     JR newpos
    .left
     DEC H   ;; Left - no check needed here
    .newpos
     PUSH HL   ;; Save new position
     PUSH AF   ;; Protect A from the TEST KEY call
    .proa
     LD A,1   ;; key code for right arrow
     CALL &BB1E  ;; KM TEST KEY
     JR Z,lftar  ;; Zero if not pressed
     POP AF   ;; old direction
     ADD A,1   ;; clockwise move
     CP 4   ;; check A value in range
     JR NZ,newdir2  ;; Jump if not 4
     LD A,0   ;; reset A to 0
    .newdir2
     PUSH AF   ;; new direction
     LD BC,&2000  ;; delay to separate keystrokes
    .dloop2
     DEC BC
     LD A,B
     OR C
     JR NZ,dloop2
    .lftar
     LD A,8   ;; key code for left arrow
     CALL &BB1E  ;; KM TEST KEY
     JR Z,cesc  ;; jump if not pressed
     POP AF   ;; old direction
     SUB 1   ;; Subtract: A=A-1
     JR NC,newdir  ;; Jump if Carry bit not set **
     LD A,3   ;; Reset A to 3 if below 0
    .newdir
     PUSH AF   ;; New Direction
     LD BC,&2000  ;; delay loop
    .dloop
     DEC BC   
     LD A,B
     OR C
     JR NZ,dloop
    .cesc
     LD A,66   ;; key code for ESC
     CALL &BB1E  ;; KM TEST KEY
     JR Z,check
     POP AF   ;; clear stack before return
     POP HL
     RET   ;; Return to Basic
    .check
     POP AF
     POP HL   ;; only HL really wanted
     PUSH AF   ;; save direction code
     LD A,L   ;; routine to check L value
     CP 0   ;; off top of screen?
     JR NZ,botscr
     LD L,25   ;; wrap-round, top to bottom
     JR checkh  ;; Jump to H check
    .botscr
     CP 26   ;; bottom of screen?
     JR NZ,checkh
     LD L,1   ;; move to top
    .checkh
     LD A,H   ;; check H value
     CP 0   ;; off left?
     JR NZ,offright
     LD H,40   ;; move to right edge
     JR tidy   ;; jump to end
    .offright
     CP 41   ;; off right
     JR NZ,tidy
     LD H,1   ;; move to left edge
    .tidy
     POP AF   ;; tidy up the stack
     JP loop   ;; jump to start of main loop ***
    .ship1
     defb 16,56,56,56,124,124,198,130
    .ship2
     defb 192,112,62,31,62,112,192,0
    .ship3
     defb 130,198,124,124,56,56,56,16
    .ship4
     defb 0,3,14,124,248,124,14,3 ;; data for defining the ships.


This is one of those Left/Right, point the ship in this direction kind of routine and use the foward arrow to move it in the direction it's facing. The original program (which is mainly this) comes from Amstrad CPC464 User (before it became ACU) and the program appeared to only be CPC464 friendly. A good deal of modify it just to get it to compile in Maxam was required since the original routine was using direct addresses & bytes in the Jump & Jump Relative routine and no labels!  ???  So I've tried to label the program as best as I could, result the program works. The original code never included the matrix data either, where in it was included within the BASIC Loader program, but now it should act as the BASIC program does. But I reckon there could be considerable enhancements which could be done to it if anyone is looking for a routine like this.
* Using the old Amstrad Languages :D * And create my own ;)
* Incorporating the Firmware :P
* I also like to problem solve code in BASIC :)   * And type-in Type-Ins! :D

Home Computing Weekly Programs
Popular Computing Weekly Programs
Your Computer Programs
Updated Other Program Links on Profile Page (Update April 16/15 phew!)
Programs for Turbo Pascal 3

Gryzor

Dear AA,

I typed the program that you printed in your last issue, again and again, but my Amstrad gives me an error on every line. Even if I add line numbers, when I try to run it I get errors again and I don't know how to correct them.

I noticed that you didn't print the checksums so I can check if I have typed it in correctly, but I am pretty sure I did. Also, you didn't print those dots that represent spaces, those are really useful...

Is my 464 broken?

Thank you,
Th.P.

Quote from: CP/M User on 04:14, 19 December 10
I hope no-one minds me posting this old dinosaur of a routine in here!  ???

org &4000

    .setup 
     LD A,1   ;; My crude routine for setting up Scr_Mode
     CALL &BC0E
     LD A,240  ;; Setup Symbol Table - A Holds Character value
     LD HL,ship1  ;; HL points to Symbol Data to Define to
     CALL &BBA8  ;; Firmware routine to Redefine Symbol Table.
     LD A,241
     LD HL,ship2
     CALL &BBA8
     LD A,242
     LD HL,ship3
     CALL &BBA8
     LD A,243
     LD HL,ship4
     CALL &BBA8
    .init
     ld hl,&140C  ;; Initial Position
     LD A,0   ;; Initial Direction
    .loop
     PUSH HL   ;; Start of Main Loop
     PUSH AF
     CALL &BB75  ;; TXT SET CURSOR
     POP AF
     PUSH AF
     ADD A,240  ;; graphic code
     CALL &BB5D  ;; Print
     LD BC,&0C00  ;; Start Short Delay
    .shtdel
     DEC BC   
     LD A,B
     OR C
     JR NZ,shtdel  ;; loop back if Non Zero
     POP AF
     POP HL   ;; only HL actually wanted
     PUSH HL
     PUSH AF   ;; the next call corrupts AF & HL
     CALL &BB75  ;; TXT SET CURSOR
     LD A,32   ;; code for space
     CALL &BB5D  ;; Print
     LD A,0   ;; code for up arrow
     CALL &BB1E  ;; KM TEST KEY
     JR Z,proa  ;; Jump if Key Up
     POP AF   ;; reclaim direction code
     POP HL   ;; ..and position
     CP 0   ;; Compare A with 0 - up?
     JR NZ,right  ;; Jump to check Right if Not
     DEC L   ;; Up a row
     JR newpos  ;; Jump to the next position
    .right
     CP 1   ;; Compare with 1 - right?
     JR NZ,down
     INC H   ;; Right one column
     JR newpos
    .down
     CP 2   ;; Down?
     JR NZ,left
     INC L   ;; Down a row
     JR newpos
    .left
     DEC H   ;; Left - no check needed here
    .newpos
     PUSH HL   ;; Save new position
     PUSH AF   ;; Protect A from the TEST KEY call
    .proa
     LD A,1   ;; key code for right arrow
     CALL &BB1E  ;; KM TEST KEY
     JR Z,lftar  ;; Zero if not pressed
     POP AF   ;; old direction
     ADD A,1   ;; clockwise move
     CP 4   ;; check A value in range
     JR NZ,newdir2  ;; Jump if not 4
     LD A,0   ;; reset A to 0
    .newdir2
     PUSH AF   ;; new direction
     LD BC,&2000  ;; delay to separate keystrokes
    .dloop2
     DEC BC
     LD A,B
     OR C
     JR NZ,dloop2
    .lftar
     LD A,8   ;; key code for left arrow
     CALL &BB1E  ;; KM TEST KEY
     JR Z,cesc  ;; jump if not pressed
     POP AF   ;; old direction
     SUB 1   ;; Subtract: A=A-1
     JR NC,newdir  ;; Jump if Carry bit not set **
     LD A,3   ;; Reset A to 3 if below 0
    .newdir
     PUSH AF   ;; New Direction
     LD BC,&2000  ;; delay loop
    .dloop
     DEC BC   
     LD A,B
     OR C
     JR NZ,dloop
    .cesc
     LD A,66   ;; key code for ESC
     CALL &BB1E  ;; KM TEST KEY
     JR Z,check
     POP AF   ;; clear stack before return
     POP HL
     RET   ;; Return to Basic
    .check
     POP AF
     POP HL   ;; only HL really wanted
     PUSH AF   ;; save direction code
     LD A,L   ;; routine to check L value
     CP 0   ;; off top of screen?
     JR NZ,botscr
     LD L,25   ;; wrap-round, top to bottom
     JR checkh  ;; Jump to H check
    .botscr
     CP 26   ;; bottom of screen?
     JR NZ,checkh
     LD L,1   ;; move to top
    .checkh
     LD A,H   ;; check H value
     CP 0   ;; off left?
     JR NZ,offright
     LD H,40   ;; move to right edge
     JR tidy   ;; jump to end
    .offright
     CP 41   ;; off right
     JR NZ,tidy
     LD H,1   ;; move to left edge
    .tidy
     POP AF   ;; tidy up the stack
     JP loop   ;; jump to start of main loop ***
    .ship1
     defb 16,56,56,56,124,124,198,130
    .ship2
     defb 192,112,62,31,62,112,192,0
    .ship3
     defb 130,198,124,124,56,56,56,16
    .ship4
     defb 0,3,14,124,248,124,14,3 ;; data for defining the ships.


This is one of those Left/Right, point the ship in this direction kind of routine and use the foward arrow to move it in the direction it's facing. The original program (which is mainly this) comes from Amstrad CPC464 User (before it became ACU) and the program appeared to only be CPC464 friendly. A good deal of modify it just to get it to compile in Maxam was required since the original routine was using direct addresses & bytes in the Jump & Jump Relative routine and no labels!  ???  So I've tried to label the program as best as I could, result the program works. The original code never included the matrix data either, where in it was included within the BASIC Loader program, but now it should act as the BASIC program does. But I reckon there could be considerable enhancements which could be done to it if anyone is looking for a routine like this.

redbox


fano

Quote from: Gryzor on 09:55, 24 December 10
Dear AA,

I typed the program that you printed in your last issue, again and again, but my Amstrad gives me an error on every line. Even if I add line numbers, when I try to run it I get errors again and I don't know how to correct them.

I noticed that you didn't print the checksums so I can check if I have typed it in correctly, but I am pretty sure I did. Also, you didn't print those dots that represent spaces, those are really useful...

Is my 464 broken?

Thank you,
Th.P.

:laugh:
"NOP" is the perfect program : short , fast and (known) bug free

Follow Easter Egg products on Facebook !

Devilmarkus

When you put your ear on a hot stove, you can smell how stupid you are ...

Amstrad CPC games in your webbrowser

JavaCPC Desktop Full Release

AMSDOS

G. Kev is gonna be real mad to see what you've done to his thread!  :-[
* Using the old Amstrad Languages :D * And create my own ;)
* Incorporating the Firmware :P
* I also like to problem solve code in BASIC :)   * And type-in Type-Ins! :D

Home Computing Weekly Programs
Popular Computing Weekly Programs
Your Computer Programs
Updated Other Program Links on Profile Page (Update April 16/15 phew!)
Programs for Turbo Pascal 3

redbox

Quote from: arnoldemu on 11:36, 30 April 10
I have a few more ideas (hardware scrolling a tilemap, software scrolling a tilemap, reducing/stopping flicker in sprites, double buffering) and then I will ask for suggestions.

Do you have the source code for this?

I am wrestling with it at the moment and would love to see how you've done it.

arnoldemu

New source:

  http://www.cpctech.org.uk/source/intpos.asm
 
  In relation to games:
 
  The example shows the position of each interrupt on the CPC.
  For games, it is much easier to change the mode or colours at the   position of an interrupt because it doesn't waste CPU time waiting for   an exact position on the screen.
 
  By changing the vsync position, you can change the relative position of   the visible part of the screen and also where the interrupts come. But   then you end up with a picture shifted within the monitor display. You   can get away with one char or so either up/down from the normal   position.
 
  CALL &8000

Posted by a Happy Kev.

 
 
My games. My Games
My website with coding examples: Unofficial Amstrad WWW Resource

arnoldemu

Quote from: redbox on 18:33, 29 December 10
Do you have the source code for this?

I am wrestling with it at the moment and would love to see how you've done it.
Yes, but nothing cleaned up.

P.M. me your e-mail address and I'll send it.
My games. My Games
My website with coding examples: Unofficial Amstrad WWW Resource

arnoldemu

New source:

http://www.cpctech.org.uk/source/scrdim.asm

This example shows:
1. position and time between CPC interrupts
2. how you can modify hsync/vsync/vdisp/hdisp to position the screen how you want (it's interactive!)
3. Then depending on vdisp/hdisp, the approx amount of ram used (really it depends on Register 9 and it's hardcoded here, and also the way the CPC screen is arranged means the calculation in this example is not perfect).
 
  In relation to games:

This example gives an idea about how the amount of ram used changes depending on the width/height of the displayed screen.
NOTE that if hardware scrolling was used, the amount of ram used would always be 16K (or 32k if overscan) because of the way the hardware scrolling is done.

  CALL &8000 to run it.
My games. My Games
My website with coding examples: Unofficial Amstrad WWW Resource

Devilmarkus

Quote from: arnoldemu on 12:01, 01 January 11
New source:

  http://www.cpctech.org.uk/source/intpos.asm
 

Freezes after using cursor keys?
Seem to work on 6128 only?!?
When you put your ear on a hot stove, you can smell how stupid you are ...

Amstrad CPC games in your webbrowser

JavaCPC Desktop Full Release

Devilmarkus

When you put your ear on a hot stove, you can smell how stupid you are ...

Amstrad CPC games in your webbrowser

JavaCPC Desktop Full Release

arnoldemu

Quote from: Devilmarkus on 17:08, 01 January 11
Freezes after using cursor keys?
Seem to work on 6128 only?!?
hmmm.. I only tested in on Winape.
it doesn't use 6128 specific code.
You have to be careful you don't move the screen outside of the normal range or the monitor can't cope.
Also not sure it works on CRTC type 2.
My games. My Games
My website with coding examples: Unofficial Amstrad WWW Resource

arnoldemu

Quote from: Devilmarkus on 17:09, 01 January 11
Freezes, too?!?
Not on winape.. I will build it for another emu later and see if it works ok.
I do need to stop it flickering and also I need to slow down the keys ;)
My games. My Games
My website with coding examples: Unofficial Amstrad WWW Resource

Devilmarkus

Quote from: arnoldemu on 21:56, 17 September 10
http://www.cpctech.org.uk/source/sampplay.asm

New source:

- Shows how to play samples using digiblaster, amdrum and AY sound chip.
- All source sample data should be raw (e.g. no headers), 8-bit signed samples.
You can use Markus' tools to make this.
- shows how to create an RSX

Markus has been using similar code in his new productions.

I re-assembled the code today.
Is it possible that there's something wrong with |DRIVER,0 ? (AY driver)
I just hear crap here... ?!?
When you put your ear on a hot stove, you can smell how stupid you are ...

Amstrad CPC games in your webbrowser

JavaCPC Desktop Full Release

arnoldemu

New source:

http://www.cpctech.org.uk/source/os_spr.asm
 
This example shows how to draw a sprite to an overscan screen. The important part here is the "scr_next_line" code.
There may be a better shorter way to do this, but this one works.

The screen is the "32k" overscan type, suitable for crtc type 2.

Control the sprite with cursors. Sprite can disapear when moving because of monitor drawing deleted version of sprite before drawing freshly drawn sprite, but the functionality is working.

Another method is used here to avoid flicker when sprite is not moving: I store previous coordinates of sprite, if these are updated I then delete and draw the sprite, otherwise I do nothing.

NOTE: I have also adjusted the screen start base so that the "problem" screen address is on the left side, meaning the code for "scr next byte" is just an inc hl. If I used a different base, then a special "scr next byte" case would be needed to cope with &07ff->&4000 case.


My games. My Games
My website with coding examples: Unofficial Amstrad WWW Resource

Sykobee (Briggsy)

Thanks for that code, I'm learning by example and that's great.

TFM

Flickering can be omitted by choosing the right time to start undraw/draw sprite. If the sprite is in the upper half of the screen, then start after interrupt 3 (occurt right in middle hight of the screen). If the sprite is in the lower half of the screen then start at interrupt 0 (frame flyback). Unclear?
TFM of FutureSoft
Also visit the CPC and Plus users favorite OS: FutureOS - The Revolution on CPC6128 and 6128Plus

arnoldemu

Quote from: TFM/FS on 23:29, 28 February 11
Flickering can be omitted by choosing the right time to start undraw/draw sprite. If the sprite is in the upper half of the screen, then start after interrupt 3 (occurt right in middle hight of the screen). If the sprite is in the lower half of the screen then start at interrupt 0 (frame flyback). Unclear?
Yes it can be done this way.
I have read of other ways too.
So, when I have a bit more time I will experiment with various ways to avoid flicker.

But methods include:

1. Sorting sprite by Y coordinate and then drawing them from top to bottom.
2. Sorting sprite by Y coordinate and then drawing them from bottom to top.
3. As you draw each sprite, erase 1 scanline, draw 1 scanline and repeat until all sprite is drawn. (this reduces flicker to a few pixels or one line).
4. double buffering.

The flicker comes because the sprite is erased completely and then drawn after.
At the top of the screen, the "monitor" has drawn the erased sprite, so that it never draws the sprite in it's new location.

When you move the sprite down the screen, there has been enough time to erase the sprite and draw it before the monitor then draws it correctly.

So although you can sort the sprites in Y and draw them this way, or choose to draw them at a different interrupt, you will still have to think where on the screen you need to erase the sprite.

So it's not exactly as simple as you say ;)

I am also talking about a general method that works with many sprites and not just 1.
My games. My Games
My website with coding examples: Unofficial Amstrad WWW Resource

Powered by SMFPacks Menu Editor Mod