易码技术论坛

 找回密码
 加入易码
搜索
查看: 1545|回复: 9

[求助] 老菜鸟要问几个BAS问题。。。

[复制链接]
发表于 2008-5-18 07:46:41 | 显示全部楼层 |阅读模式
当初在高中时一直在编BAS游戏,经常到各大论坛上看,后来升大学了,由于有了手机,就把文曲星搁浅了。
前几天手机丢失,英语四级考试在即,于是又拿起了文曲星,发现里面以前编的程序,突然又有做游戏的激情了,可是发现自己忘了很多东西。
于是到各论坛,想查找相关的资料,发现文曲星空间站在维修,而主站和易码都换了风格,很多附件丢失,文字也有错,根本无从查找。
=================
注:我的文曲星是NC3000
=================
1)有比较全面一点的NC3000的PEEK,CALL表吗?
2)有比较详细点的批量法或速读法的教程吗?具体如何操作能详细说说吗?
比如说我在屏幕上画了一幅画,如何才能让这个滚屏读图器读取?
10 DATA (数据)
20 DATA (数据)
30 DATA (数据)
40 FOR I=20480 TO 20529:READ A: POKE I,A:FOR I=20560 TO 20571:READ A: POKE I,A
50 NEXT GRAH
60 INPUT "START PIC NUM:";SPN:INPUT "END PIC NUM:";EPN:CLS: POKE 801,SPN: POKE 802 EPN+1
70 OPEN "L" FOR RANDOM AS#1 LEN=20
80 FIELD #1,1 AS A$:SPN=PEEK(801):EPN=PEEK(802):FOR I=704 TO 803: POKE I,O:NEXT
90 FOR K=SPN*80-79 TO EPN*80-81
100 GET #1,K:CALL 20560:CALL 20480
110 NEXT K:GET #1,80*EPN-80:CALL 20560
3)如果我把一幅图片以以上读图器能读的格式存到DAT文件中,如何在它后面继续存N幅图片?好像不能用APPEND吧?最多能存多少幅?
4)在红色激情的《我是大角》中,可以在任意指定为止显示自己画的地图块,好像是16*16的吧?那能不能在任意位置显示任意大小的图块呢?如果不行,那有哪些大小的可以?(有32*32和8*8的最好)
5)关于2和3,还有个问题,当初好像用那种方法可以在BAS上实现灰度图,应该是连续在屏幕上显示图片吧。请问那个程序该怎么编?

================================
我看了以下的文章,附加一个:
================================

GVB显图4法(总结) --shuyufeng  


注:仅测试过NC2600c
地址说明:
6592~8191: (图形缓冲区)
24575~24575-N: (GVB数据存储区.N为数据长度.注:该区数据由尾至头存储)

1.直接读取: (极速显图法)
如:
10 OPEN "XXX" FOR RANDOM AS#1 LEN=100
20 POKE 26254,192: POKE 26258,25:REM 读到图片显存
30 POKE 26262,64: POKE 26267,6:REM 每次读的大小
40 P=LOF(1)/1600-1:REM 图片张数
50 FOR Q=0 TO P
60 SE=Q*1600:REM 读文件的位置.当SE以20为步长递增或递减时可以实现滚图(SE=定值*1600+N:N=N+20)
70 H=INT(SE/256): L=SE-H*256
80 POKE 47446,L: POKE 47447,H:CALL 26207
90 NEXT:GOTO 20
注:贼快的方法.简单强大.显示b16图片效果也不错.该法单图DATA文件大小:1600

2.批量法(有点难度.被我称为欺骗法)
说明:当GVB中出现A$="XXX"等语句时GVB会把A$写入缓存.并记录A$的地址.此法要做的就是改变GVB记下的A$地址.
例:
10 CLEAR:CLS
20 A$="":B$=""
30 A=47302: DS=PEEK(A)+PEEK(A+1)*256:REM DS---第20条语句中A$&B$等的开始地址
40 POKE DS+2,200:REM A$的字符串长度
50 POKE DS+3,LD: POKE DS+4,HD:REM HD*256+LD=字符串开始地址
60 POKE DS+7,200: REM B$字符串的长度
70 POKE DS+8,192: POKE DS+9,2:REM 2*256+192=704(字符缓存开始地址)
80 LEST B$=A$: POKE 914,1: PRINT: POKE 914,0:END
注: POKE 914,1(显示小字体)POKE 914,0(显示大字体.GRAPH模式下不可用)DATA文件大小1600

3.矩行作图法: (研究中...)
10 POKE 34731,9
20 POKE X+Y*256,N:REM POKE图片数据到内存.X+Y*256为地址
30 POKE 152,X: POKE 153,Y:REM 2k6c好像要POKE 146,X: POKE 147,Y
40 BOX X,Y,X+XX,Y+YY,1,0:REM XX&YY为图片宽与高

=========================
要把以上的方法改为NC3000能用的,要如何修改?

========================

[ 本帖最后由 hdjackie 于 2008-5-18 07:50 编辑 ]
发表于 2008-5-18 08:44:01 | 显示全部楼层
对BAS+6502不熟悉的飘过

PS:应该有很多教程的啊,搜索看看,要不官网那里看看
 楼主| 发表于 2008-5-18 08:56:39 | 显示全部楼层
找过了,找到了很多,可是没有我想要的呀。
谢谢你,我继续等待。
1.JPG
发表于 2008-5-18 10:28:02 | 显示全部楼层
对于你说 改成NC3000能用
我想,你得先把NC3000的资料找到

比如

20 POKE 26254,192: POKE 26258,25:REM 读到图片显存

NC3000的图片显存是什么,你就把他改为对应值就可以
 楼主| 发表于 2008-5-18 10:31:29 | 显示全部楼层
找了一下,找到了这个:

最近发现有些人想用NC3000的批量法,但却不知道如何得到变量储存地址,所以我发了这一帖,希望新手能看的懂。

如果对批量法不了解的,可以在空间站上看这一帖

虾米们看的批量法



关于批量法,最主要的就是找到变量储存地址,NC3000的变量储存地址在$2000(十进制的8192,也就是显存后面)+文件长度。一般的程序,用到批量法的都是把程序写完后再到资源管理里面查看长度,这样在编程序时很不方便,每修改一次都要重新查看,所以我想,是不是文件长度都在内存里面存着呢?于是就写了下面的程序:

10 K=00000:HI=INT(K/256): LO=K-HI*256 //K用来储存文件长度
20 FOR W=2000 TO 3000
30 IF PEEK(W)<>LO THEN 60
40 IF PEEK(W+1)<>HI THEN 60
50 PRINT W
60 NEXT
70 END
80 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
90 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
100 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
110 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX //用来占位置

编好后储存,再到资源管理中得到文件大小,我的是294,然后修改程序 ,把K=00000改为K=00294(前面的0不能去掉!),程序变为:

10 K=00294:HI=INT(K/256): LO=K-HI*256
20 FOR W=2000 TO 3000
30 IF PEEK(W)<>LO THEN 60
40 IF PEEK(W+1)<>HI THEN 60
50 PRINT W
60 NEXT
70 END
80 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
90 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
100 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
110 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

然后运行程序,便可得到储存文件长度的内存地址了。我运行后是显示了三个地址:2246,2276,2299。经测试, 三个地址都表示文件长度。

所以,在批量法中,就可以直接在程序中写 DZ=PEEK(2246)+PEEK(2247)*256+8192了,修改了程序也不需要重新再查看文件长度了,是不是方便多了?

顺便说一下如何在GVB 中贴图

其实贴图就是用到了系统函数 INT $CA09,而LINE则调用了INT $CA0B,并且它们参数的地址相同,于是就可以把GVB 中的$CA0B改为$CA09,如此就可以实现贴图。同样的,我们用上面类似的寻找程序中的INT $CA0B所在的位置:

10 K=00294:A=00:B=11:C=202 //INT $CA0B的机器码

20 FOR W=16384 TO 65535

30 IF PEEK(W)<>A THEN 60

40 IF PEEK(W+1)<>B THEN 60

45 IF PEEK(W+2)<>C THEN 60

50 PRINT W

60 NEXT

70 END



运行后便可得到地址34666

因此我们POKE 34667,9,然后LINE X,Y,X+HIGHT,Y+WIDTH就可以贴图了,再POKE 34667,11 便可以用LINE话直线了。图象信息的地址需要POKE到146,147。

例如,你的图片存在地址5000,长16,宽16,要显示在(10,10)的位置,则程序如下:

HI=INT(5000/256)

LO=5000-HI*256

POKE 34667,9

POKE 146,LO

POKE 147,HI

LINE 10,10,10+16,10+16

END

[ 本帖最后由 hdjackie 于 2008-5-18 10:32 编辑 ]
发表于 2008-6-5 07:03:45 | 显示全部楼层
中断号 该页里该中断的地址 含义
0501 438C   //CheckCreatSuperBlock   测试超级块
0502 439E   //InitNandRam      更新物理区/逻辑区映射表
0503 415E   //phyNandPageRead   读取一页nand(物理,不做ecc校验)
0504 4170   //phyNandPageSpareRead   读取一页nand(物理,做ecc校验)
0505 4182   //NandReadBytes      逻辑读取nand (输入:nand物理扇区号[$0888],nand物理地址偏移[088A]3,缓冲地址[$F0],长度[$09D2] 输出:[$F0]所指的缓冲区)
0506 4194   //NandPageRead      读取一页nand(逻辑)
0507 41A6   //NorReadByte      读取1字节nor
0508 41B8   //NorReadBytes      读取多字节nor
0509 41CA   //getpwd      根据指定的inode号(0x8d2~0x8d3)找出对应的目录名(0x88d)
050A 41DC 7D3A   //opendir      测试目录是否可列出(输入:$088d,输出:C==0可列出,C==1不可列出)
050B 41EE   //mkdir        创建目录
050C 4200 7DAE   //readdir      读取目录
050D 4212   //chdir        切换工作目录(0x88d)
050E 4224   //unlink      删除文件(文件名:0x88d)
050F 4236   //rmdir        删除目录(0x88d)
0510 4248   //rename      重命名(原名称:0x88d,新名称:0x918)
0511 425A   //chmod        永久修改指定文件属性1(参数:0x8ff)
0512 426C   //fchmod      暂时修改指定文件属性1
0513 427E   //access      测试指定文件属性1
0514 4290   //getfilelen      获取文件长度
0515 42A2   //open        打开或创建文件
0516 42B4   //read        读文件
0517 42C6   //close        关闭文件
0518 42D8   //write        写文件
0519 42EA   //lseek        更改文件读写指针位置
051A 437A   //find_inode      读inode
051B 42FC   //ReadOneInode      读一个inode
051C 430E   //InodeReclaimAll   空间整理_释放已删除空间
051D 4320   //SectorReclaim      空间整理_删除无用的分配表信息
051E 4332   //InodeValidCheck   重启时空间整理A
051F 4344   //SectorReclaimCheck   重启时空间整理B
0520 4356   //ud_inode_in_corps
0521 4368   //find_corpse
0522 414C   //stst
0523 413A   //closeall      关闭所有文件
0524 4128   //NandFlashFormat
0525 40F2   //sys_open
0526 4104   //sys_read
0527 4116   //sys_lseek
0528 40E0   //explorer
0529 40CE   //CheckNandId
052A 4098   //New_UpGradeNcode
052B 40AA   //UpGradeNcode
052C 40BC   //UpGradeInit
052D 4074   //Get_NandFlash_Block
052E 4086   //Get_p_1st_Block

094D B26C   //PlaySleep 关闭声音播放
094E B551   //PlayInit 初始化播放
094F B220   //PlayStop 暂停声音播放
0950 B375   //PlayFile 播放声音文件
0951 B595   //SetVolume 设置音量($03e9)

C001   //reset        重启
C002   //clear_memory      清空特殊地址
C003   //init_port      初始化io端口
C004   //open_803_lcd      打开803lcd
C005   //wait_key      按键停顿
C006   //repeat_key      键盘延迟
C007   //unputkey
C008   //proc_sys_event   通用系统事件
C009   //if_pushed
C00A   //sys_key_proc
C00B   //exe_down
C00C   //ReadByte      读1bytes nor flash
C00D   //WriteByte      写1bytes nor flash
C00E   //ReadBytes      读nor flash
C00F   //WriteBytes      写nor flash
C010   //Read4K      读4K nor flash
C011   //Write4K      写4K nor flash
C012   //B4KAddrConvert   4K地址转换
C013   //ToBlockForDB      找出数据库的物理块
C014   //BusGetAllBlock   找出名片的物理块表
C015   //BlkReqForNCDB
C016   //RawBlkReqForNCDB
C017   //FormatNCDB      格式化数据库区块
C018   //GetFreeBlkCount   获取数据库的可用区块
C019   //SectorErase      擦除块
C01A   //SysSectorErase   擦除系统块
C01B   //io_chk_same      判断ram和flash块是否相同
C01C   //FL1Read      读flash
C01D   //FL1Write      写flash
C01E   //FLBytesRead
C01F   //FLBytesWrite
C020   //Inf_ReadBytes      读取nor flash的出厂信息
C021   //lcd_bright      屏幕亮度
C022   //my_check_bout      初始化检查
C023   //com_download
C024   //FormatSuperBlock
C025   //FormatOther
C026   //WriteBytes_sys

C701 D963   //get_16x16_font   获取16x16字模   中文(输入:[$92](汉字内码)   输出字模地址0280)
C702 D9F8   //ccg
C703 DEBB   //get_8x10_font      获取8x10字模   英文(输入:A(ASCII码)      输出字模地址0280)
C704 DDB8   //get_8x16_font      获取8x16字模   英文(输入:A(ASCII码)      输出字模地址0280)
C705 DBE8   //get_12x12_font   获取12x12字模   中文(输入:[$92](汉字内码)   输出字模地址0280)
C706 DE56   //get_6x12_font      获取6x12字模   英文(输入:A(ASCII码)      输出字模地址0280)
C707 CD01   //flash_cursor      闪动光标
C708 C6AB   //write_8x8_font   写8x8字模
C709 CA4A   //write_8x16_code   写8x16码
C70A C6F7   //write_8x16_font   写8x16字模
C70B C743   //write_16x16_font   写16x16字模
C70C CA51   //write_16x16_code   写16x16码
C70D C838   //write_6x12_font   写6x12字模
C70E C4CA   //write_6x12_code   写6x12码
C70F D125   //write_6x12_lable   写6x12标号
C710 C4D1   //write_12x12_code1   写12x12码
C711 D1AA   //write_8x10_lable   写8x10标号
C712 D1DC   //write_8x10_font   写8x10字模
C713 CA70   //write_ascii      写ascll码
C714 CAA8   //write_one_char   写一个字符
C715 CA88   //write_chi_code   写中文码
C716 CA58   //write_ascii_tiny   写小的ascii码
C717 CB66   //update_one_line   更新一行屏幕
C718 C198   //update_lcd      刷新屏幕
C719 C1A2   //update_lcd_0      刷新屏幕0
C71A D0D6   //update_Icon      刷新屏幕两边的数码管
C71B D120   //wefont      写英文
C71C D11B   //wcfont      写中文
C71D CCA6   //convert_scr      转换
C71E CC40   //convert_nline_ser
C71F CC65   //convert_part
C720 C4F7   //get_char_index
C721 C5D9   //get_char_posi
C722 C4D8   //cal_curr_CPR_RPS
C723 CC35   //move_CharAttr_0
C724 CBA3   //clear_line      清除一行
C725 C509   //get_large_char_index
C726 C667   //check_attr
C727 C51D   //get_small_char_index
C728 C8D6   //write_12x12_font   写12x12字模
C729 D71D   //clrscreen      清除图形缓存
C72A D6A1   //clear_screen      清除文字缓存
C72B D6B3   //clear_nline_ser   清除某一行屏幕
C72C D5B1   //set_disp_bar
C72D D649   //disp_bcd      显示bcd码
C72E D474   //int2trf      int to trf
C72F D407   //gb_int2trf
C730 D3EA   //trf2int
C731 D3A0   //gb_trf2int
C732 D789   //to_number      转为数字
C733 D4A4   //bin2bcd      把数字转成字符
C734 D533   //bcd4bin
C735 D7B9   //recover_Icon
C736 D4DE   //bin3bcd
C737 D73D   //clr_but_icon

CA01 C9E9   //to_ascii
CA02 C8A4   //int_divd
CA03 C9B0   //mul_ax
CA04 C2BB   //put_dot
CA05 C2B3   //get_dot
CA06 C1F1   //Dr_squre
CA07 C18A   //Dr_block
CA08 C2F8   //Dr_line
CA09 C05F   //w_block
CA0A C193   //block_draw 方块
CA0B C301   //line_draw 线
CA0C C1FA   //squre_draw 方快
CA0D C031   //write_block
CA0E C524   //circle_draw 圆
CA0F C54B   //ellipse_draw 椭圆
CA10 C514   //fill_circle 填充圆
CA11 C51C   //fill_ellipse 填充椭圆
CA12 CA2E   //Open_win 仿win信息框
CA13 CA4F   //Refresh_win
CA14 D29A   //rollmenu 等级棒
CA15 D5E8   //proc_menu1 通用菜单
CA16 D982   //show_in_find 正在查找
CA17 DA02   //show_no_find 没有找到

CB01 C57B   //bbs_oldmon 进入系统debug
CB02 CD11   //proc_menu
CB03 D11D   //offset_next_item
CB04 D1A8   //get_key_word
CB05 D674   //float
CB06 D24F   //input 输入法
CB07 D27B   //inputz
CB08 C894   //data_view
CB09 D7D7   //show_help 显示帮助
CB0A D83F   //arrow_2
CB0B DAE3   //NCWholeToPC
CB0C DAEB   //NCWholeFromPC

以上是杨家将很早以前发的NC3000中断表................的一部分,我只把常用的发上来
想要call的话,知道这些就足够了吧..

[ 本帖最后由 windybell 于 2008-6-5 07:08 编辑 ]
发表于 2008-6-5 07:19:26 | 显示全部楼层
回答第3个问题先~

append是绝对行不通的,它只能给顺序结构的dat文件添加数据。你需要的仅仅是把存有图片数据的dat文件以随机存取模式(RANDOM)打开,设定缓冲区长度之后,从文件后面一块一块加进去罢了。依照你那个读图器的代码来看...恩,一幅图的长度是1600,可以把缓冲区设为100,然后分16次把数据PUT到文件末尾就好了。
基本上就是下面这个操作了。
OPEN "FILE" FOR RANDOM AS #1 LEN=100
FIELD #1,100 AS D$
I=LOF(1)/100
FOR J=1 TO 16
LSET D$=我也不晓得该等于啥...反正就是你的数据呗
PUT #1,I+J
NEXT
CLOSE #1
发表于 2008-6-5 08:14:03 | 显示全部楼层
第4个问题
这个就关系到GVB的局限性了
因为显存里每字节对应屏幕上并列的8个点,想在GVB里通过POKE直接把数据写到显存里的话,每次poke都必须同时改动8个点,所以所谓的在任意位置显示图片,最小的图片大小应该是8x1(如果这么小也算是图的话......=.=),而且显示的横坐标只能是8的整数倍。
希望横坐标不是整数倍也不是不行,只要通过计算,得出显存该位置现在对应的数据就成。下面举个例子
假设我的机器是NC3K(显存开始的位置为6592)。在屏幕最上方,坐标(8,0)~(15,0)画一条长度为16的直线,这条直线就是我们最初的图形,现在它开始的横坐标还是8的整数倍。POKE 6592,0: POKE 6593,255: POKE 6594,255。
现在我希望把这幅图片(拜托把这条线想像成图片吧=.=)坐移3个坐标,那么在显存里实际应该是这样的:

00000000 11111111 11111111
变成
00000111 11111111 11111000
我要进行的操作是POKE 6592,7: POKE 6593,255: POKE 6594,248
看起来似乎不是很难,操作起来也不是很难,实际上根本就不难。
因为我的图片是一条黑线,背景又是单纯的白色,移动图片后那3个地址对应的数据一看就知道了,当然不会难。但是如果我的图片是个16x16的文字,就不那么好办了。数据不好算就是个大问题。
虽然不是不能算出来,不过你想要算法的话自己稍微琢磨一下也可以轻易得出,这里给出左移时计算显存中一个字节的算法(不考虑边界):
T=PEEK(A) 读取A地址处的数据
S=T*2^N 二进制中左移N个单位,其实就是乘以N个2
T=T-INT(S/256)*256 去掉上一步中多出来的部分,如果化为2进制的话,即只留最右边的8位
P=PEEK(A+1) 读取A右侧相邻的地址中的数据
T=T+INT(P/(2^(7-N))) 先右移7-N位,取整之后就是需要移过来的部分,加到T上去。
POKE A,T 算完后将数据送入该地址
这个算法中,假设要计算的地址是A(你想成上面的6593也可以),需要左移N个单位(默认N<8)。S、T、P都是临时使用的变量。
简化后的公式是T=PEEK(A):S=T*2^N: POKE A,T-INT(S/256)*256+INT(PEEK(A+1)/(2^(7-N)))
相信任何人都能看出这个算法的繁杂。需要显示到任意位置不是不可能,如果图片比较大,用GVB来计算并处理的话效率就太低了。红鸡并不是不能够做到这点,之所以只在8的整数倍处贴图,不过是因为处理起来比较简单。
真正想高效地在任意位置贴图,只用使用GVB+汇编。上面这个公式,在汇编里有专门的指令(ROL)来执行,比GVB不知道快多少倍。
作为高级语言的GVB,虽然好理解,但是在这种细节方面就没办法不输给机器语言了..

[ 本帖最后由 windybell 于 2008-6-5 08:17 编辑 ]
发表于 2008-6-5 08:20:26 | 显示全部楼层
第5个问题
同楼上,这个也关系到GVB的局限性
LZ所说的显示灰度图片的BAS程序一定是典型的GVB+Mcode程序。不靠汇编,单以GVB的效率,根本无法保证图片的刷新率(连显示一幅图都麻烦死=.=)
发表于 2008-6-5 11:45:00 | 显示全部楼层
大家都很积极啊。看来BAS很有希望的。
您需要登录后才可以回帖 登录 | 加入易码

本版积分规则

Archiver|手机版|小黑屋|EMAX Studio

GMT+8, 2024-4-16 12:10 , Processed in 0.013007 second(s), 21 queries .

Powered by Discuz! X3.4

© 2001-2017 Comsenz Inc.

快速回复 返回顶部 返回列表